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.
383 gdk_screen_get_system_colormap (GdkScreen *screen)
385 GdkColormap *colormap = NULL;
386 GdkColormapPrivateX11 *private;
387 GdkScreenX11 *screen_x11;
389 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
390 screen_x11 = GDK_SCREEN_X11 (screen);
392 if (screen_x11->system_colormap)
393 return screen_x11->system_colormap;
395 colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
396 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
398 private->screen = screen;
399 colormap->visual = gdk_screen_get_system_visual (screen);
401 private->xcolormap = DefaultColormapOfScreen (screen_x11->xscreen);
402 private->private_val = FALSE;
404 private->hash = NULL;
405 private->last_sync_time = 0;
406 private->info = NULL;
408 colormap->colors = NULL;
409 colormap->size = colormap->visual->colormap_size;
411 switch (colormap->visual->type)
413 case GDK_VISUAL_GRAYSCALE:
414 case GDK_VISUAL_PSEUDO_COLOR:
415 private->info = g_new0 (GdkColorInfo, colormap->size);
416 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
417 (GEqualFunc) gdk_color_equal);
419 case GDK_VISUAL_STATIC_GRAY:
420 case GDK_VISUAL_STATIC_COLOR:
421 case GDK_VISUAL_DIRECT_COLOR:
422 colormap->colors = g_new (GdkColor, colormap->size);
423 gdk_colormap_sync (colormap, TRUE);
425 case GDK_VISUAL_TRUE_COLOR:
429 gdk_colormap_add (colormap);
430 screen_x11->system_colormap = colormap;
436 * gdk_colormap_get_system_size:
438 * Returns the size of the system's default colormap.
439 * (See the description of struct #GdkColormap for an
440 * explanation of the size of a colormap.)
442 * Return value: the size of the system's default colormap.
445 gdk_colormap_get_system_size (void)
447 return DisplayCells (GDK_SCREEN_XDISPLAY (gdk_screen_get_default()),
448 GDK_SCREEN_X11 (gdk_screen_get_default())->screen_num);
452 * gdk_colormap_change:
453 * @colormap: a #GdkColormap.
454 * @ncolors: the number of colors to change.
456 * Changes the value of the first @ncolors in a private colormap
457 * to match the values in the <structfield>colors</structfield>
458 * array in the colormap. This function is obsolete and
459 * should not be used. See gdk_color_change().
462 gdk_colormap_change (GdkColormap *colormap,
465 GdkColormapPrivateX11 *private;
474 g_return_if_fail (GDK_IS_COLORMAP (colormap));
476 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
478 if (private->screen->closed)
481 xdisplay = GDK_SCREEN_XDISPLAY (private->screen);
482 palette = g_new (XColor, ncolors);
484 switch (colormap->visual->type)
486 case GDK_VISUAL_GRAYSCALE:
487 case GDK_VISUAL_PSEUDO_COLOR:
488 for (i = 0; i < ncolors; i++)
490 palette[i].pixel = colormap->colors[i].pixel;
491 palette[i].red = colormap->colors[i].red;
492 palette[i].green = colormap->colors[i].green;
493 palette[i].blue = colormap->colors[i].blue;
494 palette[i].flags = DoRed | DoGreen | DoBlue;
497 XStoreColors (xdisplay, private->xcolormap, palette, ncolors);
500 case GDK_VISUAL_DIRECT_COLOR:
501 visual = colormap->visual;
503 shift = visual->red_shift;
504 max_colors = 1 << visual->red_prec;
505 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
507 for (i = 0; i < size; i++)
509 palette[i].pixel = i << shift;
510 palette[i].red = colormap->colors[i].red;
511 palette[i].flags = DoRed;
514 XStoreColors (xdisplay, private->xcolormap, palette, size);
516 shift = visual->green_shift;
517 max_colors = 1 << visual->green_prec;
518 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
520 for (i = 0; i < size; i++)
522 palette[i].pixel = i << shift;
523 palette[i].green = colormap->colors[i].green;
524 palette[i].flags = DoGreen;
527 XStoreColors (xdisplay, private->xcolormap, palette, size);
529 shift = visual->blue_shift;
530 max_colors = 1 << visual->blue_prec;
531 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
533 for (i = 0; i < size; i++)
535 palette[i].pixel = i << shift;
536 palette[i].blue = colormap->colors[i].blue;
537 palette[i].flags = DoBlue;
540 XStoreColors (xdisplay, private->xcolormap, palette, size);
552 * @colormap: a #GdkColormap.
553 * @contiguous: if %TRUE, the colors should be allocated
554 * in contiguous color cells.
555 * @planes: an array in which to store the plane masks.
556 * @nplanes: the number of planes to allocate. (Or zero,
557 * to indicate that the color allocation should not be planar.)
558 * @pixels: an array into which to store allocated pixel values.
559 * @npixels: the number of pixels in each plane to allocate.
561 * Allocates colors from a colormap. This function
562 * is obsolete. See gdk_colormap_alloc_colors().
563 * For full documentation of the fields, see
564 * the Xlib documentation for <function>XAllocColorCells()</function>.
569 gdk_colors_alloc (GdkColormap *colormap,
576 GdkColormapPrivateX11 *private;
580 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), 0);
582 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
584 if (private->screen->closed)
587 return_val = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen),
588 private->xcolormap,contiguous, planes,
589 nplanes, pixels, npixels);
592 for (i=0; i<npixels; i++)
594 private->info[pixels[i]].ref_count++;
595 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
599 return return_val != 0;
602 /* This is almost identical to gdk_colormap_free_colors.
609 * @colormap: a #GdkColormap.
610 * @pixels: the pixel values of the colors to free.
611 * @npixels: the number of values in @pixels.
612 * @planes: the plane masks for all planes to free, OR'd together.
614 * Frees colors allocated with gdk_colors_alloc(). This
615 * function is obsolete. See gdk_colormap_free_colors().
618 gdk_colors_free (GdkColormap *colormap,
623 GdkColormapPrivateX11 *private;
624 gulong *pixels_to_free;
625 gint npixels_to_free = 0;
628 g_return_if_fail (GDK_IS_COLORMAP (colormap));
629 g_return_if_fail (pixels != NULL);
631 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
633 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
634 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
637 pixels_to_free = g_new (gulong, npixels);
639 for (i=0; i<npixels; i++)
641 gulong pixel = pixels[i];
643 if (private->info[pixel].ref_count)
645 private->info[pixel].ref_count--;
647 if (private->info[pixel].ref_count == 0)
649 pixels_to_free[npixels_to_free++] = pixel;
650 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
651 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
652 private->info[pixel].flags = 0;
657 if (npixels_to_free && !private->screen->closed)
658 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
659 pixels_to_free, npixels_to_free, planes);
660 g_free (pixels_to_free);
663 /* This is almost identical to gdk_colors_free.
668 * gdk_colormap_free_colors:
669 * @colormap: a #GdkColormap.
670 * @colors: the colors to free.
671 * @ncolors: the number of colors in @colors.
673 * Frees previously allocated colors.
676 gdk_colormap_free_colors (GdkColormap *colormap,
680 GdkColormapPrivateX11 *private;
685 g_return_if_fail (GDK_IS_COLORMAP (colormap));
686 g_return_if_fail (colors != NULL);
688 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
690 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
691 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
694 pixels = g_new (gulong, ncolors);
696 for (i=0; i<ncolors; i++)
698 gulong pixel = colors[i].pixel;
700 if (private->info[pixel].ref_count)
702 private->info[pixel].ref_count--;
704 if (private->info[pixel].ref_count == 0)
706 pixels[npixels++] = pixel;
707 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
708 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
709 private->info[pixel].flags = 0;
714 if (npixels && !private->screen->closed)
715 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
721 /********************
723 ********************/
725 /* Try to allocate a single color using XAllocColor. If it succeeds,
726 * cache the result in our colormap, and store in ret.
729 gdk_colormap_alloc1 (GdkColormap *colormap,
733 GdkColormapPrivateX11 *private;
736 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
738 xcolor.red = color->red;
739 xcolor.green = color->green;
740 xcolor.blue = color->blue;
741 xcolor.pixel = color->pixel;
742 xcolor.flags = DoRed | DoGreen | DoBlue;
744 if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
746 ret->pixel = xcolor.pixel;
747 ret->red = xcolor.red;
748 ret->green = xcolor.green;
749 ret->blue = xcolor.blue;
751 if (ret->pixel < colormap->size)
753 if (private->info[ret->pixel].ref_count) /* got a duplicate */
755 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
756 &xcolor.pixel, 1, 0);
760 colormap->colors[ret->pixel] = *color;
761 colormap->colors[ret->pixel].pixel = ret->pixel;
762 private->info[ret->pixel].ref_count = 1;
764 g_hash_table_insert (private->hash,
765 &colormap->colors[ret->pixel],
766 &colormap->colors[ret->pixel]);
778 gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
785 GdkColormapPrivateX11 *private;
790 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
792 if (private->private_val)
795 for (i=0; i<ncolors; i++)
797 while ((index < colormap->size) && (private->info[index].ref_count != 0))
800 if (index < colormap->size)
802 colors[i].pixel = index;
804 private->info[index].ref_count++;
805 private->info[i].flags |= GDK_COLOR_WRITEABLE;
814 pixels = g_new (gulong, ncolors);
815 /* Allocation of a writeable color cells */
817 status = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
818 FALSE, NULL, 0, pixels, ncolors);
821 for (i=0; i<ncolors; i++)
823 colors[i].pixel = pixels[i];
824 private->info[pixels[i]].ref_count++;
825 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
831 return status ? ncolors : 0;
836 gdk_colormap_alloc_colors_private (GdkColormap *colormap,
843 GdkColormapPrivateX11 *private;
845 XColor *store = g_new (XColor, ncolors);
849 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
852 /* First, store the colors we have room for */
855 for (i=0; i<ncolors; i++)
859 while ((index < colormap->size) && (private->info[index].ref_count != 0))
862 if (index < colormap->size)
864 store[nstore].red = colors[i].red;
865 store[nstore].blue = colors[i].blue;
866 store[nstore].green = colors[i].green;
867 store[nstore].pixel = index;
872 colors[i].pixel = index;
873 private->info[index].ref_count++;
880 XStoreColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
884 if (nremaining > 0 && best_match)
886 /* Get best matches for remaining colors */
888 gchar *available = g_new (gchar, colormap->size);
889 for (i = 0; i < colormap->size; i++)
892 for (i=0; i<ncolors; i++)
896 index = gdk_colormap_match_color (colormap,
901 colors[i] = colormap->colors[index];
902 private->info[index].ref_count++;
912 return (ncolors - nremaining);
916 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
923 GdkColormapPrivateX11 *private;
928 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
931 for (i=0; i<ncolors; i++)
935 if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
943 if (nremaining > 0 && best_match)
945 gchar *available = g_new (gchar, colormap->size);
946 for (i = 0; i < colormap->size; i++)
947 available[i] = ((private->info[i].ref_count == 0) ||
948 !(private->info[i].flags & GDK_COLOR_WRITEABLE));
949 gdk_colormap_sync (colormap, FALSE);
951 while (nremaining > 0)
953 for (i=0; i<ncolors; i++)
957 index = gdk_colormap_match_color (colormap, &colors[i], available);
960 if (private->info[index].ref_count)
962 private->info[index].ref_count++;
963 colors[i] = colormap->colors[index];
969 if (gdk_colormap_alloc1 (colormap,
970 &colormap->colors[index],
979 available[index] = FALSE;
987 success[i] = 2; /* flag as permanent failure */
995 /* Change back the values we flagged as permanent failures */
998 for (i=0; i<ncolors; i++)
1001 nremaining = nfailed;
1004 return (ncolors - nremaining);
1008 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
1012 gboolean best_match,
1015 GdkColormapPrivateX11 *private;
1016 GdkColor *lookup_color;
1018 gint nremaining = 0;
1020 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1022 /* Check for an exact match among previously allocated colors */
1024 for (i=0; i<ncolors; i++)
1028 lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
1031 private->info[lookup_color->pixel].ref_count++;
1032 colors[i].pixel = lookup_color->pixel;
1040 /* If that failed, we try to allocate a new color, or approxmiate
1041 * with what we can get if best_match is TRUE.
1045 if (private->private_val)
1046 return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
1048 return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
1055 * gdk_colormap_alloc_colors:
1056 * @colormap: a #GdkColormap.
1057 * @colors: The color values to allocate. On return, the pixel
1058 * values for allocated colors will be filled in.
1059 * @ncolors: The number of colors in @colors.
1060 * @writeable: If %TRUE, the colors are allocated writeable
1061 * (their values can later be changed using gdk_color_change()).
1062 * Writeable colors cannot be shared between applications.
1063 * @best_match: If %TRUE, GDK will attempt to do matching against
1064 * existing colors if the colors cannot be allocated as requested.
1065 * @success: An array of length @ncolors. On return, this
1066 * indicates whether the corresponding color in @colors was
1067 * sucessfully allocated or not.
1069 * Allocates colors from a colormap.
1071 * Return value: The number of colors that were not sucessfully
1075 gdk_colormap_alloc_colors (GdkColormap *colormap,
1079 gboolean best_match,
1082 GdkColormapPrivateX11 *private;
1085 gint nremaining = 0;
1088 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), ncolors);
1089 g_return_val_if_fail (colors != NULL, ncolors);
1091 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1093 if (private->screen->closed)
1096 for (i=0; i<ncolors; i++)
1101 switch (colormap->visual->type)
1103 case GDK_VISUAL_PSEUDO_COLOR:
1104 case GDK_VISUAL_GRAYSCALE:
1106 return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
1107 writeable, best_match, success);
1109 return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
1110 writeable, best_match, success);
1113 case GDK_VISUAL_DIRECT_COLOR:
1114 case GDK_VISUAL_TRUE_COLOR:
1115 visual = colormap->visual;
1117 for (i=0; i<ncolors; i++)
1119 colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
1120 ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
1121 ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
1125 case GDK_VISUAL_STATIC_GRAY:
1126 case GDK_VISUAL_STATIC_COLOR:
1127 for (i=0; i<ncolors; i++)
1129 xcolor.red = colors[i].red;
1130 xcolor.green = colors[i].green;
1131 xcolor.blue = colors[i].blue;
1132 xcolor.pixel = colors[i].pixel;
1133 xcolor.flags = DoRed | DoGreen | DoBlue;
1135 if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
1137 colors[i].pixel = xcolor.pixel;
1149 * gdk_colormap_query_color:
1150 * @colormap: a #GdkColormap
1151 * @pixel: pixel value in hardware display format
1152 * @result: #GdkColor with red, green, blue fields initialized
1154 * Locates the RGB color in @colormap corresponding to the given
1155 * hardware pixel @pixel. @pixel must be a valid pixel in the
1156 * colormap; it's a programmer error to call this function with a
1157 * pixel which is not in the colormap. Hardware pixels are normally
1158 * obtained from gdk_colormap_alloc_colors(), or from a #GdkImage. (A
1159 * #GdkImage contains image data in hardware format, a #GdkPixbuf
1160 * contains image data in a canonical 24-bit RGB format.)
1162 * This function is rarely useful; it's used for example to
1163 * implement the eyedropper feature in #GtkColorSelection.
1167 gdk_colormap_query_color (GdkColormap *colormap,
1173 GdkColormapPrivateX11 *private;
1175 g_return_if_fail (GDK_IS_COLORMAP (colormap));
1177 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1179 visual = gdk_colormap_get_visual (colormap);
1181 switch (visual->type) {
1182 case GDK_VISUAL_DIRECT_COLOR:
1183 case GDK_VISUAL_TRUE_COLOR:
1184 result->red = 65535. * (double)((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
1185 result->green = 65535. * (double)((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
1186 result->blue = 65535. * (double)((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
1188 case GDK_VISUAL_STATIC_GRAY:
1189 case GDK_VISUAL_GRAYSCALE:
1190 result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
1192 case GDK_VISUAL_STATIC_COLOR:
1193 xcolor.pixel = pixel;
1194 if (!private->screen->closed)
1196 XQueryColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1197 result->red = xcolor.red;
1198 result->green = xcolor.green;
1199 result->blue = xcolor.blue;
1202 result->red = result->green = result->blue = 0;
1204 case GDK_VISUAL_PSEUDO_COLOR:
1205 g_return_if_fail (pixel < colormap->size);
1206 result->red = colormap->colors[pixel].red;
1207 result->green = colormap->colors[pixel].green;
1208 result->blue = colormap->colors[pixel].blue;
1211 g_assert_not_reached ();
1218 * @colormap: a #GdkColormap.
1219 * @color: a #GdkColor, with the color to change
1220 * in the <structfield>pixel</structfield> field,
1221 * and the new value in the remaining fields.
1223 * Changes the value of a color that has already
1224 * been allocated. If @colormap is not a private
1225 * colormap, then the color must have been allocated
1226 * using gdk_colormap_alloc_colors() with the
1227 * @writeable set to %TRUE.
1229 * Return value: %TRUE if the color was successfully changed.
1232 gdk_color_change (GdkColormap *colormap,
1235 GdkColormapPrivateX11 *private;
1238 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1239 g_return_val_if_fail (color != NULL, FALSE);
1241 xcolor.pixel = color->pixel;
1242 xcolor.red = color->red;
1243 xcolor.green = color->green;
1244 xcolor.blue = color->blue;
1245 xcolor.flags = DoRed | DoGreen | DoBlue;
1247 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1248 if (!private->screen->closed)
1249 XStoreColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1255 * gdk_x11_colormap_foreign_new:
1256 * @visual: a #GdkVisual
1257 * @xcolormap: The XID of a colormap with visual @visual
1259 * If xcolormap refers to a colormap previously known to GTK+,
1260 * returns a new reference to the existing #GdkColormap object,
1261 * otherwise creates a new GdkColormap object and returns that
1263 * Return value: the #GdkColormap object for @xcolormap.
1264 * Free with g_object_unref(). Note that for colormap created
1265 * with gdk_x11_colormap_foreign_new(), unref'ing the last
1266 * reference to the object will only free the #GdkColoramp
1267 * object and not call XFreeColormap()
1272 gdk_x11_colormap_foreign_new (GdkVisual *visual,
1275 GdkColormap *colormap;
1277 GdkColormapPrivateX11 *private;
1279 g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
1280 g_return_val_if_fail (xcolormap != None, NULL);
1282 screen = gdk_visual_get_screen (visual);
1284 if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1285 GDK_SCREEN_XNUMBER (screen)));
1286 return g_object_ref (gdk_screen_get_system_colormap (screen));
1288 colormap = gdk_colormap_lookup (screen, xcolormap);
1290 return g_object_ref (colormap);
1292 colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
1293 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1295 colormap->visual = visual;
1297 private->screen = screen;
1298 private->xcolormap = xcolormap;
1299 private->xdisplay = GDK_SCREEN_XDISPLAY (screen);
1300 private->private_val = FALSE;
1302 colormap->size = visual->colormap_size;
1304 switch (colormap->visual->type)
1306 case GDK_VISUAL_GRAYSCALE:
1307 case GDK_VISUAL_PSEUDO_COLOR:
1308 private->info = g_new0 (GdkColorInfo, colormap->size);
1309 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
1310 (GEqualFunc) gdk_color_equal);
1312 case GDK_VISUAL_STATIC_GRAY:
1313 case GDK_VISUAL_STATIC_COLOR:
1314 case GDK_VISUAL_DIRECT_COLOR:
1315 colormap->colors = g_new (GdkColor, colormap->size);
1316 gdk_colormap_sync (colormap, TRUE);
1318 case GDK_VISUAL_TRUE_COLOR:
1322 gdk_colormap_add (colormap);
1329 * gdkx_colormap_get:
1330 * @xcolormap: the XID of a colormap for the default screen.
1332 * Returns a #GdkColormap corresponding to a X colormap;
1333 * this function only works if the colormap is already
1334 * known to GTK+ (a colormap created by GTK+ or the default
1335 * colormap for the screen), since GTK+
1337 * Always use gdk_x11_colormap_foreign_new() instead.
1339 * Return value: the existing #GdkColormap object if it was
1340 * already known to GTK+, otherwise warns and return
1344 gdkx_colormap_get (Colormap xcolormap)
1346 GdkScreen *screen = gdk_screen_get_default ();
1347 GdkColormap *colormap;
1349 if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1350 GDK_SCREEN_XNUMBER (screen)));
1351 return g_object_ref (gdk_screen_get_system_colormap (screen));
1353 colormap = gdk_colormap_lookup (screen, xcolormap);
1355 return g_object_ref (colormap);
1357 g_warning ("Colormap passed to gdkx_colormap_get\n"
1358 "does not previously exist");
1364 gdk_colormap_match_color (GdkColormap *cmap,
1366 const gchar *available)
1370 gint rdiff, gdiff, bdiff;
1373 g_return_val_if_fail (cmap != NULL, 0);
1374 g_return_val_if_fail (color != NULL, 0);
1376 colors = cmap->colors;
1380 for (i = 0; i < cmap->size; i++)
1382 if ((!available) || (available && available[i]))
1384 rdiff = (color->red - colors[i].red);
1385 gdiff = (color->green - colors[i].green);
1386 bdiff = (color->blue - colors[i].blue);
1388 sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1403 gdk_colormap_lookup (GdkScreen *screen,
1406 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1408 if (screen_x11->colormap_hash)
1409 return g_hash_table_lookup (screen_x11->colormap_hash, &xcolormap);
1415 gdk_colormap_add (GdkColormap *cmap)
1417 GdkScreenX11 *screen_x11;
1418 GdkColormapPrivateX11 *private;
1420 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1421 screen_x11 = GDK_SCREEN_X11 (private->screen);
1423 if (!screen_x11->colormap_hash)
1424 screen_x11->colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
1425 (GEqualFunc) gdk_colormap_equal);
1427 g_hash_table_insert (screen_x11->colormap_hash, &private->xcolormap, cmap);
1431 gdk_colormap_remove (GdkColormap *cmap)
1433 GdkScreenX11 *screen_x11;
1434 GdkColormapPrivateX11 *private;
1436 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1437 screen_x11 = GDK_SCREEN_X11 (private->screen);
1439 if (screen_x11->colormap_hash)
1440 g_hash_table_remove (screen_x11->colormap_hash, &private->xcolormap);
1444 gdk_colormap_hash (Colormap *colormap)
1450 gdk_colormap_equal (Colormap *a,
1457 * gdk_x11_colormap_get_xdisplay:
1458 * @colormap: a #GdkColormap.
1460 * Returns the display of a #GdkColormap.
1462 * Return value: an Xlib <type>Display*</type>.
1465 gdk_x11_colormap_get_xdisplay (GdkColormap *colormap)
1467 GdkColormapPrivateX11 *private;
1469 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), NULL);
1471 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1473 return private->xdisplay;
1477 * gdk_x11_colormap_get_xcolormap:
1478 * @colormap: a #GdkColormap.
1480 * Returns the X colormap belonging to a #GdkColormap.
1482 * Return value: an Xlib <type>Colormap</type>.
1485 gdk_x11_colormap_get_xcolormap (GdkColormap *colormap)
1487 GdkColormapPrivateX11 *private;
1489 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), None);
1491 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1493 if (private->screen->closed)
1496 return private->xcolormap;
1500 * gdk_colormap_get_screen:
1501 * @cmap: a #GdkColormap
1503 * Gets the screen for which this colormap was created.
1505 * Return value: the screen for which this colormap was created.
1510 gdk_colormap_get_screen (GdkColormap *cmap)
1512 g_return_val_if_fail (GDK_IS_COLORMAP (cmap), NULL);
1514 return GDK_COLORMAP_PRIVATE_DATA (cmap)->screen;