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/.
31 #include "gdkinternals.h"
33 #include "gdkprivate-x11.h"
34 #include "gdkscreen-x11.h"
36 typedef struct _GdkColormapPrivateX11 GdkColormapPrivateX11;
38 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);
148 G_OBJECT_CLASS (parent_class)->finalize (object);
153 * @visual: a #GdkVisual.
154 * @allocate: if %TRUE, the newly created colormap will be
155 * a private colormap, and all colors in it will be
156 * allocated for the applications use.
158 * Creates a new colormap for the given visual.
160 * Return value: the new #GdkColormap.
163 gdk_colormap_new (GdkVisual *visual,
166 GdkColormap *colormap;
167 GdkColormapPrivateX11 *private;
174 /* FIXME when object properties settle down, there needs to be some
175 * kind of default construction (and construct-only arguments)
178 g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
180 colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
181 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
183 colormap->visual = visual;
184 private->screen = gdk_visual_get_screen (visual);
186 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
187 xdisplay = GDK_SCREEN_XDISPLAY (private->screen);
188 xrootwin = GDK_SCREEN_XROOTWIN (private->screen);
190 colormap->size = visual->colormap_size;
192 switch (visual->type)
194 case GDK_VISUAL_GRAYSCALE:
195 case GDK_VISUAL_PSEUDO_COLOR:
196 private->info = g_new0 (GdkColorInfo, colormap->size);
197 colormap->colors = g_new (GdkColor, colormap->size);
199 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
200 (GEqualFunc) gdk_color_equal);
202 private->private_val = allocate;
203 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
204 xvisual, (allocate) ? (AllocAll) : (AllocNone));
208 GdkVisual *system_visual;
209 XColor *default_colors;
210 gint n_default_colors;
212 system_visual = gdk_screen_get_system_visual (private->screen);
213 n_default_colors = MIN (system_visual->colormap_size, colormap->size);
215 default_colors = g_new (XColor, colormap->size);
217 for (i = 0; i < n_default_colors; i++)
218 default_colors[i].pixel = i;
220 XQueryColors (xdisplay,
221 DefaultColormapOfScreen (GDK_SCREEN_X11 (private->screen)->xscreen),
222 default_colors, n_default_colors);
224 for (i = 0; i < n_default_colors; i++)
226 colormap->colors[i].pixel = default_colors[i].pixel;
227 colormap->colors[i].red = default_colors[i].red;
228 colormap->colors[i].green = default_colors[i].green;
229 colormap->colors[i].blue = default_colors[i].blue;
232 gdk_colormap_change (colormap, n_default_colors);
234 g_free (default_colors);
238 case GDK_VISUAL_DIRECT_COLOR:
239 private->private_val = TRUE;
240 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
242 colormap->colors = g_new (GdkColor, colormap->size);
244 size = 1 << visual->red_prec;
245 for (i = 0; i < size; i++)
246 colormap->colors[i].red = i * 65535 / (size - 1);
248 size = 1 << visual->green_prec;
249 for (i = 0; i < size; i++)
250 colormap->colors[i].green = i * 65535 / (size - 1);
252 size = 1 << visual->blue_prec;
253 for (i = 0; i < size; i++)
254 colormap->colors[i].blue = i * 65535 / (size - 1);
256 gdk_colormap_change (colormap, colormap->size);
259 case GDK_VISUAL_STATIC_GRAY:
260 case GDK_VISUAL_STATIC_COLOR:
261 private->private_val = FALSE;
262 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
265 colormap->colors = g_new (GdkColor, colormap->size);
266 gdk_colormap_sync (colormap, TRUE);
269 case GDK_VISUAL_TRUE_COLOR:
270 private->private_val = FALSE;
271 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
276 gdk_colormap_add (colormap);
282 gdk_colormap_sync_palette (GdkColormap *colormap)
284 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
290 xpalette = g_new (XColor, colormap->size);
292 for (i = 0; i < colormap->size; i++)
294 if (!private->info || private->info[i].ref_count == 0)
296 xpalette[nlookup].pixel = i;
297 xpalette[nlookup].red = 0;
298 xpalette[nlookup].green = 0;
299 xpalette[nlookup].blue = 0;
304 XQueryColors (GDK_SCREEN_XDISPLAY (private->screen),
305 private->xcolormap, xpalette, nlookup);
307 for (i = 0; i < nlookup; i++)
309 gulong pixel = xpalette[i].pixel;
310 colormap->colors[pixel].pixel = pixel;
311 colormap->colors[pixel].red = xpalette[i].red;
312 colormap->colors[pixel].green = xpalette[i].green;
313 colormap->colors[pixel].blue = xpalette[i].blue;
320 gdk_colormap_sync_direct_color (GdkColormap *colormap)
322 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
323 GdkVisual *visual = colormap->visual;
327 xpalette = g_new (XColor, colormap->size);
329 for (i = 0; i < colormap->size; i++)
332 (((i << visual->red_shift) & visual->red_mask) |
333 ((i << visual->green_shift) & visual->green_mask) |
334 ((i << visual->blue_shift) & visual->blue_mask));
337 XQueryColors (GDK_SCREEN_XDISPLAY (private->screen),
338 private->xcolormap, xpalette, colormap->size);
340 for (i = 0; i < colormap->size; i++)
342 colormap->colors[i].pixel = xpalette[i].pixel;
343 colormap->colors[i].red = xpalette[i].red;
344 colormap->colors[i].green = xpalette[i].green;
345 colormap->colors[i].blue = xpalette[i].blue;
351 #define MIN_SYNC_TIME 2
354 gdk_colormap_sync (GdkColormap *colormap,
358 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
360 g_return_if_fail (GDK_IS_COLORMAP (colormap));
362 if (private->screen->closed)
365 current_time = time (NULL);
366 if (!force && ((current_time - private->last_sync_time) < MIN_SYNC_TIME))
369 private->last_sync_time = current_time;
371 if (colormap->visual->type == GDK_VISUAL_DIRECT_COLOR)
372 gdk_colormap_sync_direct_color (colormap);
374 gdk_colormap_sync_palette (colormap);
378 * gdk_screen_get_system_colormap:
379 * @screen: a #GdkScreen
381 * Gets the system's default colormap for @screen
383 * Returns: the default colormap for @screen.
388 gdk_screen_get_system_colormap (GdkScreen *screen)
390 GdkColormap *colormap = NULL;
391 GdkColormapPrivateX11 *private;
392 GdkScreenX11 *screen_x11;
394 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
395 screen_x11 = GDK_SCREEN_X11 (screen);
397 if (screen_x11->system_colormap)
398 return screen_x11->system_colormap;
400 colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
401 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
403 private->screen = screen;
404 colormap->visual = gdk_screen_get_system_visual (screen);
406 private->xcolormap = DefaultColormapOfScreen (screen_x11->xscreen);
407 private->private_val = FALSE;
409 private->hash = NULL;
410 private->last_sync_time = 0;
411 private->info = NULL;
413 colormap->colors = NULL;
414 colormap->size = colormap->visual->colormap_size;
416 switch (colormap->visual->type)
418 case GDK_VISUAL_GRAYSCALE:
419 case GDK_VISUAL_PSEUDO_COLOR:
420 private->info = g_new0 (GdkColorInfo, colormap->size);
421 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
422 (GEqualFunc) gdk_color_equal);
424 case GDK_VISUAL_STATIC_GRAY:
425 case GDK_VISUAL_STATIC_COLOR:
426 case GDK_VISUAL_DIRECT_COLOR:
427 colormap->colors = g_new (GdkColor, colormap->size);
428 gdk_colormap_sync (colormap, TRUE);
430 case GDK_VISUAL_TRUE_COLOR:
434 gdk_colormap_add (colormap);
435 screen_x11->system_colormap = colormap;
441 * gdk_colormap_get_system_size:
443 * Returns the size of the system's default colormap.
444 * (See the description of struct #GdkColormap for an
445 * explanation of the size of a colormap.)
447 * Return value: the size of the system's default colormap.
450 gdk_colormap_get_system_size (void)
452 return DisplayCells (GDK_SCREEN_XDISPLAY (gdk_screen_get_default()),
453 GDK_SCREEN_X11 (gdk_screen_get_default())->screen_num);
457 * gdk_colormap_change:
458 * @colormap: a #GdkColormap.
459 * @ncolors: the number of colors to change.
461 * Changes the value of the first @ncolors in a private colormap
462 * to match the values in the <structfield>colors</structfield>
463 * array in the colormap. This function is obsolete and
464 * should not be used. See gdk_color_change().
467 gdk_colormap_change (GdkColormap *colormap,
470 GdkColormapPrivateX11 *private;
479 g_return_if_fail (GDK_IS_COLORMAP (colormap));
481 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
483 if (private->screen->closed)
486 xdisplay = GDK_SCREEN_XDISPLAY (private->screen);
487 palette = g_new (XColor, ncolors);
489 switch (colormap->visual->type)
491 case GDK_VISUAL_GRAYSCALE:
492 case GDK_VISUAL_PSEUDO_COLOR:
493 for (i = 0; i < ncolors; i++)
495 palette[i].pixel = colormap->colors[i].pixel;
496 palette[i].red = colormap->colors[i].red;
497 palette[i].green = colormap->colors[i].green;
498 palette[i].blue = colormap->colors[i].blue;
499 palette[i].flags = DoRed | DoGreen | DoBlue;
502 XStoreColors (xdisplay, private->xcolormap, palette, ncolors);
505 case GDK_VISUAL_DIRECT_COLOR:
506 visual = colormap->visual;
508 shift = visual->red_shift;
509 max_colors = 1 << visual->red_prec;
510 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
512 for (i = 0; i < size; i++)
514 palette[i].pixel = i << shift;
515 palette[i].red = colormap->colors[i].red;
516 palette[i].flags = DoRed;
519 XStoreColors (xdisplay, private->xcolormap, palette, size);
521 shift = visual->green_shift;
522 max_colors = 1 << visual->green_prec;
523 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
525 for (i = 0; i < size; i++)
527 palette[i].pixel = i << shift;
528 palette[i].green = colormap->colors[i].green;
529 palette[i].flags = DoGreen;
532 XStoreColors (xdisplay, private->xcolormap, palette, size);
534 shift = visual->blue_shift;
535 max_colors = 1 << visual->blue_prec;
536 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
538 for (i = 0; i < size; i++)
540 palette[i].pixel = i << shift;
541 palette[i].blue = colormap->colors[i].blue;
542 palette[i].flags = DoBlue;
545 XStoreColors (xdisplay, private->xcolormap, palette, size);
557 * @colormap: a #GdkColormap.
558 * @contiguous: if %TRUE, the colors should be allocated
559 * in contiguous color cells.
560 * @planes: an array in which to store the plane masks.
561 * @nplanes: the number of planes to allocate. (Or zero,
562 * to indicate that the color allocation should not be planar.)
563 * @pixels: an array into which to store allocated pixel values.
564 * @npixels: the number of pixels in each plane to allocate.
566 * Allocates colors from a colormap. This function
567 * is obsolete. See gdk_colormap_alloc_colors().
568 * For full documentation of the fields, see
569 * the Xlib documentation for <function>XAllocColorCells()</function>.
574 gdk_colors_alloc (GdkColormap *colormap,
581 GdkColormapPrivateX11 *private;
585 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
587 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
589 if (private->screen->closed)
592 return_val = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen),
593 private->xcolormap,contiguous, planes,
594 nplanes, pixels, npixels);
597 for (i = 0; i < npixels; i++)
599 private->info[pixels[i]].ref_count++;
600 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
604 return return_val != 0;
607 /* This is almost identical to gdk_colormap_free_colors.
614 * @colormap: a #GdkColormap.
615 * @pixels: the pixel values of the colors to free.
616 * @npixels: the number of values in @pixels.
617 * @planes: the plane masks for all planes to free, OR'd together.
619 * Frees colors allocated with gdk_colors_alloc(). This
620 * function is obsolete. See gdk_colormap_free_colors().
623 gdk_colors_free (GdkColormap *colormap,
628 GdkColormapPrivateX11 *private;
629 gulong *pixels_to_free;
630 gint npixels_to_free = 0;
633 g_return_if_fail (GDK_IS_COLORMAP (colormap));
634 g_return_if_fail (pixels != NULL);
636 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
638 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
639 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
642 pixels_to_free = g_new (gulong, npixels);
644 for (i = 0; i < npixels; i++)
646 gulong pixel = pixels[i];
648 if (private->info[pixel].ref_count)
650 private->info[pixel].ref_count--;
652 if (private->info[pixel].ref_count == 0)
654 pixels_to_free[npixels_to_free++] = pixel;
655 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
656 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
657 private->info[pixel].flags = 0;
662 if (npixels_to_free && !private->private_val && !private->screen->closed)
663 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
664 pixels_to_free, npixels_to_free, planes);
665 g_free (pixels_to_free);
668 /* This is almost identical to gdk_colors_free.
673 * gdk_colormap_free_colors:
674 * @colormap: a #GdkColormap.
675 * @colors: the colors to free.
676 * @ncolors: the number of colors in @colors.
678 * Frees previously allocated colors.
681 gdk_colormap_free_colors (GdkColormap *colormap,
685 GdkColormapPrivateX11 *private;
690 g_return_if_fail (GDK_IS_COLORMAP (colormap));
691 g_return_if_fail (colors != NULL);
693 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
695 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
696 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
699 pixels = g_new (gulong, ncolors);
701 for (i = 0; i < ncolors; i++)
703 gulong pixel = colors[i].pixel;
705 if (private->info[pixel].ref_count)
707 private->info[pixel].ref_count--;
709 if (private->info[pixel].ref_count == 0)
711 pixels[npixels++] = pixel;
712 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
713 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
714 private->info[pixel].flags = 0;
719 if (npixels && !private->private_val && !private->screen->closed)
720 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
726 /********************
728 ********************/
730 /* Try to allocate a single color using XAllocColor. If it succeeds,
731 * cache the result in our colormap, and store in ret.
734 gdk_colormap_alloc1 (GdkColormap *colormap,
738 GdkColormapPrivateX11 *private;
741 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
743 xcolor.red = color->red;
744 xcolor.green = color->green;
745 xcolor.blue = color->blue;
746 xcolor.pixel = color->pixel;
747 xcolor.flags = DoRed | DoGreen | DoBlue;
749 if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
751 ret->pixel = xcolor.pixel;
752 ret->red = xcolor.red;
753 ret->green = xcolor.green;
754 ret->blue = xcolor.blue;
756 if (ret->pixel < colormap->size)
758 if (private->info[ret->pixel].ref_count) /* got a duplicate */
760 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
761 &xcolor.pixel, 1, 0);
762 private->info[ret->pixel].ref_count++;
766 colormap->colors[ret->pixel] = *color;
767 colormap->colors[ret->pixel].pixel = ret->pixel;
768 private->info[ret->pixel].ref_count = 1;
770 g_hash_table_insert (private->hash,
771 &colormap->colors[ret->pixel],
772 &colormap->colors[ret->pixel]);
784 gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
791 GdkColormapPrivateX11 *private;
796 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
798 if (private->private_val)
801 for (i = 0; i < ncolors; i++)
803 while ((index < colormap->size) && (private->info[index].ref_count != 0))
806 if (index < colormap->size)
808 colors[i].pixel = index;
810 private->info[index].ref_count++;
811 private->info[i].flags |= GDK_COLOR_WRITEABLE;
820 pixels = g_new (gulong, ncolors);
821 /* Allocation of a writeable color cells */
823 status = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
824 FALSE, NULL, 0, pixels, ncolors);
827 for (i = 0; i < ncolors; i++)
829 colors[i].pixel = pixels[i];
831 private->info[pixels[i]].ref_count++;
832 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
838 return status ? 0 : ncolors;
843 gdk_colormap_alloc_colors_private (GdkColormap *colormap,
850 GdkColormapPrivateX11 *private;
852 XColor *store = g_new (XColor, ncolors);
856 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
858 /* First, store the colors we have room for */
861 for (i = 0; i < ncolors; i++)
865 while ((index < colormap->size) && (private->info[index].ref_count != 0))
868 if (index < colormap->size)
870 store[nstore].red = colors[i].red;
871 store[nstore].blue = colors[i].blue;
872 store[nstore].green = colors[i].green;
873 store[nstore].pixel = index;
874 store[nstore].flags = DoRed | DoGreen | DoBlue;
878 colors[i].pixel = index;
880 colormap->colors[index] = colors[i];
881 private->info[index].ref_count++;
883 g_hash_table_insert (private->hash,
884 &colormap->colors[index],
885 &colormap->colors[index]);
892 XStoreColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
896 if (nremaining > 0 && best_match)
898 /* Get best matches for remaining colors */
900 gchar *available = g_new (gchar, colormap->size);
901 for (i = 0; i < colormap->size; i++)
902 available[i] = !(private->info[i].flags & GDK_COLOR_WRITEABLE);
904 for (i = 0; i < ncolors; i++)
908 index = gdk_colormap_match_color (colormap,
913 colors[i] = colormap->colors[index];
914 private->info[index].ref_count++;
928 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
935 GdkColormapPrivateX11 *private;
940 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
942 for (i = 0; i < ncolors; i++)
946 if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
954 if (nremaining > 0 && best_match)
956 gchar *available = g_new (gchar, colormap->size);
957 for (i = 0; i < colormap->size; i++)
958 available[i] = ((private->info[i].ref_count == 0) ||
959 !(private->info[i].flags & GDK_COLOR_WRITEABLE));
960 gdk_colormap_sync (colormap, FALSE);
962 while (nremaining > 0)
964 for (i = 0; i < ncolors; i++)
968 index = gdk_colormap_match_color (colormap, &colors[i], available);
971 if (private->info[index].ref_count)
973 private->info[index].ref_count++;
974 colors[i] = colormap->colors[index];
980 if (gdk_colormap_alloc1 (colormap,
981 &colormap->colors[index],
990 available[index] = FALSE;
998 success[i] = 2; /* flag as permanent failure */
1006 /* Change back the values we flagged as permanent failures */
1009 for (i = 0; i < ncolors; i++)
1010 if (success[i] == 2)
1012 nremaining = nfailed;
1019 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
1023 gboolean best_match,
1026 GdkColormapPrivateX11 *private;
1027 GdkColor *lookup_color;
1029 gint nremaining = 0;
1031 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1033 /* Check for an exact match among previously allocated colors */
1035 for (i = 0; i < ncolors; i++)
1039 lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
1042 private->info[lookup_color->pixel].ref_count++;
1043 colors[i].pixel = lookup_color->pixel;
1051 /* If that failed, we try to allocate a new color, or approxmiate
1052 * with what we can get if best_match is TRUE.
1056 if (private->private_val)
1057 return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
1059 return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
1066 * gdk_colormap_alloc_colors:
1067 * @colormap: a #GdkColormap.
1068 * @colors: The color values to allocate. On return, the pixel
1069 * values for allocated colors will be filled in.
1070 * @ncolors: The number of colors in @colors.
1071 * @writeable: If %TRUE, the colors are allocated writeable
1072 * (their values can later be changed using gdk_color_change()).
1073 * Writeable colors cannot be shared between applications.
1074 * @best_match: If %TRUE, GDK will attempt to do matching against
1075 * existing colors if the colors cannot be allocated as requested.
1076 * @success: An array of length @ncolors. On return, this
1077 * indicates whether the corresponding color in @colors was
1078 * successfully allocated or not.
1080 * Allocates colors from a colormap.
1082 * Return value: The number of colors that were not successfully
1086 gdk_colormap_alloc_colors (GdkColormap *colormap,
1090 gboolean best_match,
1093 GdkColormapPrivateX11 *private;
1096 gint nremaining = 0;
1099 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), ncolors);
1100 g_return_val_if_fail (colors != NULL, ncolors);
1101 g_return_val_if_fail (success != NULL, ncolors);
1103 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1105 if (private->screen->closed)
1108 for (i = 0; i < ncolors; i++)
1111 switch (colormap->visual->type)
1113 case GDK_VISUAL_PSEUDO_COLOR:
1114 case GDK_VISUAL_GRAYSCALE:
1116 return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
1117 writeable, best_match, success);
1119 return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
1120 writeable, best_match, success);
1123 case GDK_VISUAL_DIRECT_COLOR:
1124 case GDK_VISUAL_TRUE_COLOR:
1125 visual = colormap->visual;
1127 for (i = 0; i < ncolors; i++)
1129 colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
1130 ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
1131 ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
1135 case GDK_VISUAL_STATIC_GRAY:
1136 case GDK_VISUAL_STATIC_COLOR:
1137 for (i = 0; i < ncolors; i++)
1139 xcolor.red = colors[i].red;
1140 xcolor.green = colors[i].green;
1141 xcolor.blue = colors[i].blue;
1142 xcolor.pixel = colors[i].pixel;
1143 xcolor.flags = DoRed | DoGreen | DoBlue;
1145 if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
1147 colors[i].pixel = xcolor.pixel;
1159 * gdk_colormap_query_color:
1160 * @colormap: a #GdkColormap
1161 * @pixel: pixel value in hardware display format
1162 * @result: #GdkColor with red, green, blue fields initialized
1164 * Locates the RGB color in @colormap corresponding to the given
1165 * hardware pixel @pixel. @pixel must be a valid pixel in the
1166 * colormap; it's a programmer error to call this function with a
1167 * pixel which is not in the colormap. Hardware pixels are normally
1168 * obtained from gdk_colormap_alloc_colors(), or from a #GdkImage. (A
1169 * #GdkImage contains image data in hardware format, a #GdkPixbuf
1170 * contains image data in a canonical 24-bit RGB format.)
1172 * This function is rarely useful; it's used for example to
1173 * implement the eyedropper feature in #GtkColorSelection.
1177 gdk_colormap_query_color (GdkColormap *colormap,
1183 GdkColormapPrivateX11 *private;
1185 g_return_if_fail (GDK_IS_COLORMAP (colormap));
1187 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1189 visual = gdk_colormap_get_visual (colormap);
1191 switch (visual->type) {
1192 case GDK_VISUAL_DIRECT_COLOR:
1193 case GDK_VISUAL_TRUE_COLOR:
1194 result->red = 65535. * (double)((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
1195 result->green = 65535. * (double)((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
1196 result->blue = 65535. * (double)((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
1198 case GDK_VISUAL_STATIC_GRAY:
1199 case GDK_VISUAL_GRAYSCALE:
1200 result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
1202 case GDK_VISUAL_STATIC_COLOR:
1203 xcolor.pixel = pixel;
1204 if (!private->screen->closed)
1206 XQueryColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1207 result->red = xcolor.red;
1208 result->green = xcolor.green;
1209 result->blue = xcolor.blue;
1212 result->red = result->green = result->blue = 0;
1214 case GDK_VISUAL_PSEUDO_COLOR:
1215 g_return_if_fail (pixel < colormap->size);
1216 result->red = colormap->colors[pixel].red;
1217 result->green = colormap->colors[pixel].green;
1218 result->blue = colormap->colors[pixel].blue;
1221 g_assert_not_reached ();
1228 * @colormap: a #GdkColormap.
1229 * @color: a #GdkColor, with the color to change
1230 * in the <structfield>pixel</structfield> field,
1231 * and the new value in the remaining fields.
1233 * Changes the value of a color that has already
1234 * been allocated. If @colormap is not a private
1235 * colormap, then the color must have been allocated
1236 * using gdk_colormap_alloc_colors() with the
1237 * @writeable set to %TRUE.
1239 * Return value: %TRUE if the color was successfully changed.
1242 gdk_color_change (GdkColormap *colormap,
1245 GdkColormapPrivateX11 *private;
1248 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1249 g_return_val_if_fail (color != NULL, FALSE);
1251 xcolor.pixel = color->pixel;
1252 xcolor.red = color->red;
1253 xcolor.green = color->green;
1254 xcolor.blue = color->blue;
1255 xcolor.flags = DoRed | DoGreen | DoBlue;
1257 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1258 if (!private->screen->closed)
1259 XStoreColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1265 * gdk_x11_colormap_foreign_new:
1266 * @visual: a #GdkVisual
1267 * @xcolormap: The XID of a colormap with visual @visual
1269 * If xcolormap refers to a colormap previously known to GTK+,
1270 * returns a new reference to the existing #GdkColormap object,
1271 * otherwise creates a new GdkColormap object and returns that
1273 * Return value: the #GdkColormap object for @xcolormap.
1274 * Free with g_object_unref(). Note that for colormap created
1275 * with gdk_x11_colormap_foreign_new(), unref'ing the last
1276 * reference to the object will only free the #GdkColoramp
1277 * object and not call XFreeColormap()
1282 gdk_x11_colormap_foreign_new (GdkVisual *visual,
1285 GdkColormap *colormap;
1287 GdkColormapPrivateX11 *private;
1289 g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
1290 g_return_val_if_fail (xcolormap != None, NULL);
1292 screen = gdk_visual_get_screen (visual);
1294 if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1295 GDK_SCREEN_XNUMBER (screen)))
1296 return g_object_ref (gdk_screen_get_system_colormap (screen));
1298 colormap = gdk_colormap_lookup (screen, xcolormap);
1300 return g_object_ref (colormap);
1302 colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
1303 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1305 colormap->visual = visual;
1307 private->screen = screen;
1308 private->xcolormap = xcolormap;
1309 private->private_val = FALSE;
1311 colormap->size = visual->colormap_size;
1313 switch (colormap->visual->type)
1315 case GDK_VISUAL_GRAYSCALE:
1316 case GDK_VISUAL_PSEUDO_COLOR:
1317 private->info = g_new0 (GdkColorInfo, colormap->size);
1318 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
1319 (GEqualFunc) gdk_color_equal);
1321 case GDK_VISUAL_STATIC_GRAY:
1322 case GDK_VISUAL_STATIC_COLOR:
1323 case GDK_VISUAL_DIRECT_COLOR:
1324 colormap->colors = g_new (GdkColor, colormap->size);
1325 gdk_colormap_sync (colormap, TRUE);
1327 case GDK_VISUAL_TRUE_COLOR:
1331 gdk_colormap_add (colormap);
1338 * gdkx_colormap_get:
1339 * @xcolormap: the XID of a colormap for the default screen.
1341 * Returns a #GdkColormap corresponding to a X colormap;
1342 * this function only works if the colormap is already
1343 * known to GTK+ (a colormap created by GTK+ or the default
1344 * colormap for the screen), since GTK+
1346 * Always use gdk_x11_colormap_foreign_new() instead.
1348 * Return value: the existing #GdkColormap object if it was
1349 * already known to GTK+, otherwise warns and return
1353 gdkx_colormap_get (Colormap xcolormap)
1355 GdkScreen *screen = gdk_screen_get_default ();
1356 GdkColormap *colormap;
1358 if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1359 GDK_SCREEN_XNUMBER (screen)));
1360 return g_object_ref (gdk_screen_get_system_colormap (screen));
1362 colormap = gdk_colormap_lookup (screen, xcolormap);
1364 return g_object_ref (colormap);
1366 g_warning ("Colormap passed to gdkx_colormap_get\n"
1367 "does not previously exist");
1373 gdk_colormap_match_color (GdkColormap *cmap,
1375 const gchar *available)
1379 gint rdiff, gdiff, bdiff;
1382 colors = cmap->colors;
1386 for (i = 0; i < cmap->size; i++)
1388 if ((!available) || (available && available[i]))
1390 rdiff = (color->red - colors[i].red);
1391 gdiff = (color->green - colors[i].green);
1392 bdiff = (color->blue - colors[i].blue);
1394 sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1409 gdk_colormap_lookup (GdkScreen *screen,
1412 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1414 if (screen_x11->colormap_hash)
1415 return g_hash_table_lookup (screen_x11->colormap_hash, &xcolormap);
1421 gdk_colormap_add (GdkColormap *cmap)
1423 GdkScreenX11 *screen_x11;
1424 GdkColormapPrivateX11 *private;
1426 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1427 screen_x11 = GDK_SCREEN_X11 (private->screen);
1429 if (!screen_x11->colormap_hash)
1430 screen_x11->colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
1431 (GEqualFunc) gdk_colormap_equal);
1433 g_hash_table_insert (screen_x11->colormap_hash, &private->xcolormap, cmap);
1437 gdk_colormap_remove (GdkColormap *cmap)
1439 GdkScreenX11 *screen_x11;
1440 GdkColormapPrivateX11 *private;
1442 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1443 screen_x11 = GDK_SCREEN_X11 (private->screen);
1445 if (screen_x11->colormap_hash)
1446 g_hash_table_remove (screen_x11->colormap_hash, &private->xcolormap);
1450 gdk_colormap_hash (Colormap *colormap)
1456 gdk_colormap_equal (Colormap *a,
1463 * gdk_x11_colormap_get_xdisplay:
1464 * @colormap: a #GdkColormap.
1466 * Returns the display of a #GdkColormap.
1468 * Return value: an Xlib <type>Display*</type>.
1471 gdk_x11_colormap_get_xdisplay (GdkColormap *colormap)
1473 GdkColormapPrivateX11 *private;
1475 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), NULL);
1477 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1479 return GDK_SCREEN_XDISPLAY (private->screen);
1483 * gdk_x11_colormap_get_xcolormap:
1484 * @colormap: a #GdkColormap.
1486 * Returns the X colormap belonging to a #GdkColormap.
1488 * Return value: an Xlib <type>Colormap</type>.
1491 gdk_x11_colormap_get_xcolormap (GdkColormap *colormap)
1493 GdkColormapPrivateX11 *private;
1495 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), None);
1497 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1499 if (private->screen->closed)
1502 return private->xcolormap;
1506 * gdk_colormap_get_screen:
1507 * @cmap: a #GdkColormap
1509 * Gets the screen for which this colormap was created.
1511 * Return value: the screen for which this colormap was created.
1516 gdk_colormap_get_screen (GdkColormap *cmap)
1518 g_return_val_if_fail (GDK_IS_COLORMAP (cmap), NULL);
1520 return GDK_COLORMAP_PRIVATE_DATA (cmap)->screen;