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);
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 (visual != NULL, 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 XColor *default_colors;
210 default_colors = g_new (XColor, colormap->size);
212 for (i = 0; i < colormap->size; i++)
213 default_colors[i].pixel = i;
215 XQueryColors (xdisplay,
216 DefaultColormapOfScreen (GDK_SCREEN_X11 (private->screen)->xscreen),
217 default_colors, colormap->size);
219 for (i = 0; i < colormap->size; i++)
221 colormap->colors[i].pixel = default_colors[i].pixel;
222 colormap->colors[i].red = default_colors[i].red;
223 colormap->colors[i].green = default_colors[i].green;
224 colormap->colors[i].blue = default_colors[i].blue;
227 gdk_colormap_change (colormap, colormap->size);
229 g_free (default_colors);
233 case GDK_VISUAL_DIRECT_COLOR:
234 private->private_val = TRUE;
235 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
237 colormap->colors = g_new (GdkColor, colormap->size);
239 size = 1 << visual->red_prec;
240 for (i = 0; i < size; i++)
241 colormap->colors[i].red = i * 65535 / (size - 1);
243 size = 1 << visual->green_prec;
244 for (i = 0; i < size; i++)
245 colormap->colors[i].green = i * 65535 / (size - 1);
247 size = 1 << visual->blue_prec;
248 for (i = 0; i < size; i++)
249 colormap->colors[i].blue = i * 65535 / (size - 1);
251 gdk_colormap_change (colormap, colormap->size);
254 case GDK_VISUAL_STATIC_GRAY:
255 case GDK_VISUAL_STATIC_COLOR:
256 private->private_val = FALSE;
257 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
260 colormap->colors = g_new (GdkColor, colormap->size);
261 gdk_colormap_sync (colormap, TRUE);
264 case GDK_VISUAL_TRUE_COLOR:
265 private->private_val = FALSE;
266 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
271 gdk_colormap_add (colormap);
277 gdk_colormap_sync_palette (GdkColormap *colormap)
279 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
285 xpalette = g_new (XColor, colormap->size);
287 for (i = 0; i < colormap->size; i++)
289 if (!private->info || private->info[i].ref_count == 0)
291 xpalette[nlookup].pixel = i;
292 xpalette[nlookup].red = 0;
293 xpalette[nlookup].green = 0;
294 xpalette[nlookup].blue = 0;
299 XQueryColors (GDK_SCREEN_XDISPLAY (private->screen),
300 private->xcolormap, xpalette, nlookup);
302 for (i = 0; i < nlookup; i++)
304 gulong pixel = xpalette[i].pixel;
305 colormap->colors[pixel].pixel = pixel;
306 colormap->colors[pixel].red = xpalette[i].red;
307 colormap->colors[pixel].green = xpalette[i].green;
308 colormap->colors[pixel].blue = xpalette[i].blue;
315 gdk_colormap_sync_direct_color (GdkColormap *colormap)
317 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
318 GdkVisual *visual = colormap->visual;
322 xpalette = g_new (XColor, colormap->size);
324 for (i = 0; i < colormap->size; i++)
327 (((i << visual->red_shift) & visual->red_mask) |
328 ((i << visual->green_shift) & visual->green_mask) |
329 ((i << visual->blue_shift) & visual->blue_mask));
332 XQueryColors (GDK_SCREEN_XDISPLAY (private->screen),
333 private->xcolormap, xpalette, colormap->size);
335 for (i = 0; i < colormap->size; i++)
337 colormap->colors[i].pixel = xpalette[i].pixel;
338 colormap->colors[i].red = xpalette[i].red;
339 colormap->colors[i].green = xpalette[i].green;
340 colormap->colors[i].blue = xpalette[i].blue;
346 #define MIN_SYNC_TIME 2
349 gdk_colormap_sync (GdkColormap *colormap,
353 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
355 g_return_if_fail (GDK_IS_COLORMAP (colormap));
357 if (private->screen->closed)
360 current_time = time (NULL);
361 if (!force && ((current_time - private->last_sync_time) < MIN_SYNC_TIME))
364 private->last_sync_time = current_time;
366 if (colormap->visual->type == GDK_VISUAL_DIRECT_COLOR)
367 gdk_colormap_sync_direct_color (colormap);
369 gdk_colormap_sync_palette (colormap);
373 * gdk_screen_get_system_colormap:
374 * @screen: a #GdkScreen
376 * Gets the system's default colormap for @screen
378 * Returns: the default colormap for @screen.
381 gdk_screen_get_system_colormap (GdkScreen *screen)
383 GdkColormap *colormap = NULL;
384 GdkColormapPrivateX11 *private;
385 GdkScreenX11 *screen_x11;
387 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
388 screen_x11 = GDK_SCREEN_X11 (screen);
390 if (screen_x11->system_colormap)
391 return screen_x11->system_colormap;
393 colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
394 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
396 private->screen = screen;
397 colormap->visual = gdk_screen_get_system_visual (screen);
399 private->xcolormap = DefaultColormapOfScreen (screen_x11->xscreen);
400 private->private_val = FALSE;
402 private->hash = NULL;
403 private->last_sync_time = 0;
404 private->info = NULL;
406 colormap->colors = NULL;
407 colormap->size = colormap->visual->colormap_size;
409 switch (colormap->visual->type)
411 case GDK_VISUAL_GRAYSCALE:
412 case GDK_VISUAL_PSEUDO_COLOR:
413 private->info = g_new0 (GdkColorInfo, colormap->size);
414 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
415 (GEqualFunc) gdk_color_equal);
417 case GDK_VISUAL_STATIC_GRAY:
418 case GDK_VISUAL_STATIC_COLOR:
419 case GDK_VISUAL_DIRECT_COLOR:
420 colormap->colors = g_new (GdkColor, colormap->size);
421 gdk_colormap_sync (colormap, TRUE);
423 case GDK_VISUAL_TRUE_COLOR:
427 gdk_colormap_add (colormap);
428 screen_x11->system_colormap = colormap;
434 * gdk_colormap_get_system_size:
436 * Returns the size of the system's default colormap.
437 * (See the description of struct #GdkColormap for an
438 * explanation of the size of a colormap.)
440 * Return value: the size of the system's default colormap.
443 gdk_colormap_get_system_size (void)
445 return DisplayCells (GDK_SCREEN_XDISPLAY (gdk_screen_get_default()),
446 GDK_SCREEN_X11 (gdk_screen_get_default())->screen_num);
450 * gdk_colormap_change:
451 * @colormap: a #GdkColormap.
452 * @ncolors: the number of colors to change.
454 * Changes the value of the first @ncolors in a private colormap
455 * to match the values in the <structfield>colors</structfield>
456 * array in the colormap. This function is obsolete and
457 * should not be used. See gdk_color_change().
460 gdk_colormap_change (GdkColormap *colormap,
463 GdkColormapPrivateX11 *private;
472 g_return_if_fail (GDK_IS_COLORMAP (colormap));
474 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
476 if (private->screen->closed)
479 xdisplay = GDK_SCREEN_XDISPLAY (private->screen);
480 palette = g_new (XColor, ncolors);
482 switch (colormap->visual->type)
484 case GDK_VISUAL_GRAYSCALE:
485 case GDK_VISUAL_PSEUDO_COLOR:
486 for (i = 0; i < ncolors; i++)
488 palette[i].pixel = colormap->colors[i].pixel;
489 palette[i].red = colormap->colors[i].red;
490 palette[i].green = colormap->colors[i].green;
491 palette[i].blue = colormap->colors[i].blue;
492 palette[i].flags = DoRed | DoGreen | DoBlue;
495 XStoreColors (xdisplay, private->xcolormap, palette, ncolors);
498 case GDK_VISUAL_DIRECT_COLOR:
499 visual = colormap->visual;
501 shift = visual->red_shift;
502 max_colors = 1 << visual->red_prec;
503 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
505 for (i = 0; i < size; i++)
507 palette[i].pixel = i << shift;
508 palette[i].red = colormap->colors[i].red;
509 palette[i].flags = DoRed;
512 XStoreColors (xdisplay, private->xcolormap, palette, size);
514 shift = visual->green_shift;
515 max_colors = 1 << visual->green_prec;
516 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
518 for (i = 0; i < size; i++)
520 palette[i].pixel = i << shift;
521 palette[i].green = colormap->colors[i].green;
522 palette[i].flags = DoGreen;
525 XStoreColors (xdisplay, private->xcolormap, palette, size);
527 shift = visual->blue_shift;
528 max_colors = 1 << visual->blue_prec;
529 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
531 for (i = 0; i < size; i++)
533 palette[i].pixel = i << shift;
534 palette[i].blue = colormap->colors[i].blue;
535 palette[i].flags = DoBlue;
538 XStoreColors (xdisplay, private->xcolormap, palette, size);
550 * @colormap: a #GdkColormap.
551 * @contiguous: if %TRUE, the colors should be allocated
552 * in contiguous color cells.
553 * @planes: an array in which to store the plane masks.
554 * @nplanes: the number of planes to allocate. (Or zero,
555 * to indicate that the color allocation should not be planar.)
556 * @pixels: an array into which to store allocated pixel values.
557 * @npixels: the number of pixels in each plane to allocate.
559 * Allocates colors from a colormap. This function
560 * is obsolete. See gdk_colormap_alloc_colors().
561 * For full documentation of the fields, see
562 * the Xlib documentation for <function>XAllocColorCells()</function>.
567 gdk_colors_alloc (GdkColormap *colormap,
574 GdkColormapPrivateX11 *private;
578 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), 0);
580 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
582 if (private->screen->closed)
585 return_val = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen),
586 private->xcolormap,contiguous, planes,
587 nplanes, pixels, npixels);
590 for (i=0; i<npixels; i++)
592 private->info[pixels[i]].ref_count++;
593 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
597 return return_val != 0;
600 /* This is almost identical to gdk_colormap_free_colors.
607 * @colormap: a #GdkColormap.
608 * @pixels: the pixel values of the colors to free.
609 * @npixels: the number of values in @pixels.
610 * @planes: the plane masks for all planes to free, OR'd together.
612 * Frees colors allocated with gdk_colors_alloc(). This
613 * function is obsolete. See gdk_colormap_free_colors().
616 gdk_colors_free (GdkColormap *colormap,
621 GdkColormapPrivateX11 *private;
622 gulong *pixels_to_free;
623 gint npixels_to_free = 0;
626 g_return_if_fail (GDK_IS_COLORMAP (colormap));
627 g_return_if_fail (pixels != NULL);
629 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
631 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
632 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
635 pixels_to_free = g_new (gulong, npixels);
637 for (i=0; i<npixels; i++)
639 gulong pixel = pixels[i];
641 if (private->info[pixel].ref_count)
643 private->info[pixel].ref_count--;
645 if (private->info[pixel].ref_count == 0)
647 pixels_to_free[npixels_to_free++] = pixel;
648 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
649 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
650 private->info[pixel].flags = 0;
655 if (npixels_to_free && !private->screen->closed)
656 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
657 pixels_to_free, npixels_to_free, planes);
658 g_free (pixels_to_free);
661 /* This is almost identical to gdk_colors_free.
666 * gdk_colormap_free_colors:
667 * @colormap: a #GdkColormap.
668 * @colors: the colors to free.
669 * @ncolors: the number of colors in @colors.
671 * Frees previously allocated colors.
674 gdk_colormap_free_colors (GdkColormap *colormap,
678 GdkColormapPrivateX11 *private;
683 g_return_if_fail (GDK_IS_COLORMAP (colormap));
684 g_return_if_fail (colors != NULL);
686 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
688 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
689 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
692 pixels = g_new (gulong, ncolors);
694 for (i=0; i<ncolors; i++)
696 gulong pixel = colors[i].pixel;
698 if (private->info[pixel].ref_count)
700 private->info[pixel].ref_count--;
702 if (private->info[pixel].ref_count == 0)
704 pixels[npixels++] = pixel;
705 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
706 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
707 private->info[pixel].flags = 0;
712 if (npixels && !private->screen->closed)
713 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
719 /********************
721 ********************/
723 /* Try to allocate a single color using XAllocColor. If it succeeds,
724 * cache the result in our colormap, and store in ret.
727 gdk_colormap_alloc1 (GdkColormap *colormap,
731 GdkColormapPrivateX11 *private;
734 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
736 xcolor.red = color->red;
737 xcolor.green = color->green;
738 xcolor.blue = color->blue;
739 xcolor.pixel = color->pixel;
740 xcolor.flags = DoRed | DoGreen | DoBlue;
742 if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
744 ret->pixel = xcolor.pixel;
745 ret->red = xcolor.red;
746 ret->green = xcolor.green;
747 ret->blue = xcolor.blue;
749 if (ret->pixel < colormap->size)
751 if (private->info[ret->pixel].ref_count) /* got a duplicate */
753 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
754 &xcolor.pixel, 1, 0);
758 colormap->colors[ret->pixel] = *color;
759 colormap->colors[ret->pixel].pixel = ret->pixel;
760 private->info[ret->pixel].ref_count = 1;
762 g_hash_table_insert (private->hash,
763 &colormap->colors[ret->pixel],
764 &colormap->colors[ret->pixel]);
776 gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
783 GdkColormapPrivateX11 *private;
788 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
790 if (private->private_val)
793 for (i=0; i<ncolors; i++)
795 while ((index < colormap->size) && (private->info[index].ref_count != 0))
798 if (index < colormap->size)
800 colors[i].pixel = index;
802 private->info[index].ref_count++;
803 private->info[i].flags |= GDK_COLOR_WRITEABLE;
812 pixels = g_new (gulong, ncolors);
813 /* Allocation of a writeable color cells */
815 status = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
816 FALSE, NULL, 0, pixels, ncolors);
819 for (i=0; i<ncolors; i++)
821 colors[i].pixel = pixels[i];
822 private->info[pixels[i]].ref_count++;
823 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
829 return status ? ncolors : 0;
834 gdk_colormap_alloc_colors_private (GdkColormap *colormap,
841 GdkColormapPrivateX11 *private;
843 XColor *store = g_new (XColor, ncolors);
847 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
850 /* First, store the colors we have room for */
853 for (i=0; i<ncolors; i++)
857 while ((index < colormap->size) && (private->info[index].ref_count != 0))
860 if (index < colormap->size)
862 store[nstore].red = colors[i].red;
863 store[nstore].blue = colors[i].blue;
864 store[nstore].green = colors[i].green;
865 store[nstore].pixel = index;
870 colors[i].pixel = index;
871 private->info[index].ref_count++;
878 XStoreColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
882 if (nremaining > 0 && best_match)
884 /* Get best matches for remaining colors */
886 gchar *available = g_new (gchar, colormap->size);
887 for (i = 0; i < colormap->size; i++)
890 for (i=0; i<ncolors; i++)
894 index = gdk_colormap_match_color (colormap,
899 colors[i] = colormap->colors[index];
900 private->info[index].ref_count++;
910 return (ncolors - nremaining);
914 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
921 GdkColormapPrivateX11 *private;
926 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
929 for (i=0; i<ncolors; i++)
933 if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
941 if (nremaining > 0 && best_match)
943 gchar *available = g_new (gchar, colormap->size);
944 for (i = 0; i < colormap->size; i++)
945 available[i] = ((private->info[i].ref_count == 0) ||
946 !(private->info[i].flags & GDK_COLOR_WRITEABLE));
947 gdk_colormap_sync (colormap, FALSE);
949 while (nremaining > 0)
951 for (i=0; i<ncolors; i++)
955 index = gdk_colormap_match_color (colormap, &colors[i], available);
958 if (private->info[index].ref_count)
960 private->info[index].ref_count++;
961 colors[i] = colormap->colors[index];
967 if (gdk_colormap_alloc1 (colormap,
968 &colormap->colors[index],
977 available[index] = FALSE;
985 success[i] = 2; /* flag as permanent failure */
993 /* Change back the values we flagged as permanent failures */
996 for (i=0; i<ncolors; i++)
999 nremaining = nfailed;
1002 return (ncolors - nremaining);
1006 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
1010 gboolean best_match,
1013 GdkColormapPrivateX11 *private;
1014 GdkColor *lookup_color;
1016 gint nremaining = 0;
1018 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1020 /* Check for an exact match among previously allocated colors */
1022 for (i=0; i<ncolors; i++)
1026 lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
1029 private->info[lookup_color->pixel].ref_count++;
1030 colors[i].pixel = lookup_color->pixel;
1038 /* If that failed, we try to allocate a new color, or approxmiate
1039 * with what we can get if best_match is TRUE.
1043 if (private->private_val)
1044 return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
1046 return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
1053 * gdk_colormap_alloc_colors:
1054 * @colormap: a #GdkColormap.
1055 * @colors: The color values to allocate. On return, the pixel
1056 * values for allocated colors will be filled in.
1057 * @ncolors: The number of colors in @colors.
1058 * @writeable: If %TRUE, the colors are allocated writeable
1059 * (their values can later be changed using gdk_color_change()).
1060 * Writeable colors cannot be shared between applications.
1061 * @best_match: If %TRUE, GDK will attempt to do matching against
1062 * existing colors if the colors cannot be allocated as requested.
1063 * @success: An array of length @ncolors. On return, this
1064 * indicates whether the corresponding color in @colors was
1065 * sucessfully allocated or not.
1067 * Allocates colors from a colormap.
1069 * Return value: The number of colors that were not sucessfully
1073 gdk_colormap_alloc_colors (GdkColormap *colormap,
1077 gboolean best_match,
1080 GdkColormapPrivateX11 *private;
1083 gint nremaining = 0;
1086 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), ncolors);
1087 g_return_val_if_fail (colors != NULL, ncolors);
1089 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1091 if (private->screen->closed)
1094 for (i=0; i<ncolors; i++)
1099 switch (colormap->visual->type)
1101 case GDK_VISUAL_PSEUDO_COLOR:
1102 case GDK_VISUAL_GRAYSCALE:
1104 return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
1105 writeable, best_match, success);
1107 return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
1108 writeable, best_match, success);
1111 case GDK_VISUAL_DIRECT_COLOR:
1112 case GDK_VISUAL_TRUE_COLOR:
1113 visual = colormap->visual;
1115 for (i=0; i<ncolors; i++)
1117 colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
1118 ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
1119 ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
1123 case GDK_VISUAL_STATIC_GRAY:
1124 case GDK_VISUAL_STATIC_COLOR:
1125 for (i=0; i<ncolors; i++)
1127 xcolor.red = colors[i].red;
1128 xcolor.green = colors[i].green;
1129 xcolor.blue = colors[i].blue;
1130 xcolor.pixel = colors[i].pixel;
1131 xcolor.flags = DoRed | DoGreen | DoBlue;
1133 if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
1135 colors[i].pixel = xcolor.pixel;
1147 * gdk_colormap_query_color:
1148 * @colormap: a #GdkColormap
1149 * @pixel: pixel value in hardware display format
1150 * @result: #GdkColor with red, green, blue fields initialized
1152 * Locates the RGB color in @colormap corresponding to the given
1153 * hardware pixel @pixel. @pixel must be a valid pixel in the
1154 * colormap; it's a programmer error to call this function with a
1155 * pixel which is not in the colormap. Hardware pixels are normally
1156 * obtained from gdk_colormap_alloc_colors(), or from a #GdkImage. (A
1157 * #GdkImage contains image data in hardware format, a #GdkPixbuf
1158 * contains image data in a canonical 24-bit RGB format.)
1160 * This function is rarely useful; it's used for example to
1161 * implement the eyedropper feature in #GtkColorSelection.
1165 gdk_colormap_query_color (GdkColormap *colormap,
1171 GdkColormapPrivateX11 *private;
1173 g_return_if_fail (GDK_IS_COLORMAP (colormap));
1175 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1177 visual = gdk_colormap_get_visual (colormap);
1179 switch (visual->type) {
1180 case GDK_VISUAL_DIRECT_COLOR:
1181 case GDK_VISUAL_TRUE_COLOR:
1182 result->red = 65535. * (double)((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
1183 result->green = 65535. * (double)((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
1184 result->blue = 65535. * (double)((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
1186 case GDK_VISUAL_STATIC_GRAY:
1187 case GDK_VISUAL_GRAYSCALE:
1188 result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
1190 case GDK_VISUAL_STATIC_COLOR:
1191 xcolor.pixel = pixel;
1192 if (!private->screen->closed)
1194 XQueryColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1195 result->red = xcolor.red;
1196 result->green = xcolor.green;
1197 result->blue = xcolor.blue;
1200 result->red = result->green = result->blue = 0;
1202 case GDK_VISUAL_PSEUDO_COLOR:
1203 g_return_if_fail (pixel < colormap->size);
1204 result->red = colormap->colors[pixel].red;
1205 result->green = colormap->colors[pixel].green;
1206 result->blue = colormap->colors[pixel].blue;
1209 g_assert_not_reached ();
1216 * @colormap: a #GdkColormap.
1217 * @color: a #GdkColor, with the color to change
1218 * in the <structfield>pixel</structfield> field,
1219 * and the new value in the remaining fields.
1221 * Changes the value of a color that has already
1222 * been allocated. If @colormap is not a private
1223 * colormap, then the color must have been allocated
1224 * using gdk_colormap_alloc_colors() with the
1225 * @writeable set to %TRUE.
1227 * Return value: %TRUE if the color was successfully changed.
1230 gdk_color_change (GdkColormap *colormap,
1233 GdkColormapPrivateX11 *private;
1236 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1237 g_return_val_if_fail (color != NULL, FALSE);
1239 xcolor.pixel = color->pixel;
1240 xcolor.red = color->red;
1241 xcolor.green = color->green;
1242 xcolor.blue = color->blue;
1243 xcolor.flags = DoRed | DoGreen | DoBlue;
1245 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1246 if (!private->screen->closed)
1247 XStoreColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1253 * gdk_x11_colormap_foreign_new:
1254 * @visual: a #GdkVisual
1255 * @xcolormap: The XID of a colormap with visual @visual
1257 * If xcolormap refers to a colormap previously known to GTK+,
1258 * returns a new reference to the existing #GdkColormap object,
1259 * otherwise creates a new GdkColormap object and returns that
1261 * Return value: the #GdkColormap object for @xcolormap.
1262 * Free with g_object_unref(). Note that for colormap created
1263 * with gdk_x11_colormap_foreign_new(), unref'ing the last
1264 * reference to the object will only free the #GdkColoramp
1265 * object and not call XFreeColormap()
1268 gdk_x11_colormap_foreign_new (GdkVisual *visual,
1271 GdkColormap *colormap;
1273 GdkColormapPrivateX11 *private;
1275 g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
1276 g_return_val_if_fail (xcolormap != None, NULL);
1278 screen = gdk_visual_get_screen (visual);
1280 if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1281 GDK_SCREEN_XNUMBER (screen)));
1282 return g_object_ref (gdk_screen_get_system_colormap (screen));
1284 colormap = gdk_colormap_lookup (screen, xcolormap);
1286 return g_object_ref (colormap);
1288 colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
1289 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1291 colormap->visual = visual;
1293 private->screen = screen;
1294 private->xcolormap = xcolormap;
1295 private->xdisplay = GDK_SCREEN_XDISPLAY (screen);
1296 private->private_val = FALSE;
1298 colormap->size = visual->colormap_size;
1300 switch (colormap->visual->type)
1302 case GDK_VISUAL_GRAYSCALE:
1303 case GDK_VISUAL_PSEUDO_COLOR:
1304 private->info = g_new0 (GdkColorInfo, colormap->size);
1305 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
1306 (GEqualFunc) gdk_color_equal);
1308 case GDK_VISUAL_STATIC_GRAY:
1309 case GDK_VISUAL_STATIC_COLOR:
1310 case GDK_VISUAL_DIRECT_COLOR:
1311 colormap->colors = g_new (GdkColor, colormap->size);
1312 gdk_colormap_sync (colormap, TRUE);
1314 case GDK_VISUAL_TRUE_COLOR:
1318 gdk_colormap_add (colormap);
1325 * gdkx_colormap_get:
1326 * @xcolormap: the XID of a colormap for the default screen.
1328 * Returns a #GdkColormap corresponding to a X colormap;
1329 * this function only works if the colormap is already
1330 * known to GTK+ (a colormap created by GTK+ or the default
1331 * colormap for the screen), since GTK+
1333 * Always use gdk_x11_colormap_foreign_new() instead.
1335 * Return value: the existing #GdkColormap object if it was
1336 * already known to GTK+, otherwise warns and return
1340 gdkx_colormap_get (Colormap xcolormap)
1342 GdkScreen *screen = gdk_screen_get_default ();
1343 GdkColormap *colormap;
1345 if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1346 GDK_SCREEN_XNUMBER (screen)));
1347 return g_object_ref (gdk_screen_get_system_colormap (screen));
1349 colormap = gdk_colormap_lookup (screen, xcolormap);
1351 return g_object_ref (colormap);
1353 g_warning ("Colormap passed to gdkx_colormap_get\n"
1354 "does not previously exist");
1360 gdk_colormap_match_color (GdkColormap *cmap,
1362 const gchar *available)
1366 gint rdiff, gdiff, bdiff;
1369 g_return_val_if_fail (cmap != NULL, 0);
1370 g_return_val_if_fail (color != NULL, 0);
1372 colors = cmap->colors;
1376 for (i = 0; i < cmap->size; i++)
1378 if ((!available) || (available && available[i]))
1380 rdiff = (color->red - colors[i].red);
1381 gdiff = (color->green - colors[i].green);
1382 bdiff = (color->blue - colors[i].blue);
1384 sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1399 gdk_colormap_lookup (GdkScreen *screen,
1402 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1404 if (screen_x11->colormap_hash)
1405 return g_hash_table_lookup (screen_x11->colormap_hash, &xcolormap);
1411 gdk_colormap_add (GdkColormap *cmap)
1413 GdkScreenX11 *screen_x11;
1414 GdkColormapPrivateX11 *private;
1416 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1417 screen_x11 = GDK_SCREEN_X11 (private->screen);
1419 if (!screen_x11->colormap_hash)
1420 screen_x11->colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
1421 (GEqualFunc) gdk_colormap_equal);
1423 g_hash_table_insert (screen_x11->colormap_hash, &private->xcolormap, cmap);
1427 gdk_colormap_remove (GdkColormap *cmap)
1429 GdkScreenX11 *screen_x11;
1430 GdkColormapPrivateX11 *private;
1432 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1433 screen_x11 = GDK_SCREEN_X11 (private->screen);
1435 if (screen_x11->colormap_hash)
1436 g_hash_table_remove (screen_x11->colormap_hash, &private->xcolormap);
1440 gdk_colormap_hash (Colormap *colormap)
1446 gdk_colormap_equal (Colormap *a,
1453 * gdk_x11_colormap_get_xdisplay:
1454 * @colormap: a #GdkColormap.
1456 * Returns the display of a #GdkColormap.
1458 * Return value: an Xlib <type>Display*</type>.
1461 gdk_x11_colormap_get_xdisplay (GdkColormap *colormap)
1463 GdkColormapPrivateX11 *private;
1465 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), NULL);
1467 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1469 return private->xdisplay;
1473 * gdk_x11_colormap_get_xcolormap:
1474 * @colormap: a #GdkColormap.
1476 * Returns the X colormap belonging to a #GdkColormap.
1478 * Return value: an Xlib <type>Colormap</type>.
1481 gdk_x11_colormap_get_xcolormap (GdkColormap *colormap)
1483 GdkColormapPrivateX11 *private;
1485 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), None);
1487 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1489 if (private->screen->closed)
1492 return private->xcolormap;
1496 * gdk_colormap_get_screen:
1497 * @cmap: a #GdkColormap
1499 * Gets the screen for which this colormap was created.
1501 * Return value: the screen for which this colormap was created.
1504 gdk_colormap_get_screen (GdkColormap *cmap)
1506 g_return_val_if_fail (GDK_IS_COLORMAP (cmap), NULL);
1508 return GDK_COLORMAP_PRIVATE_DATA (cmap)->screen;