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/.
33 #include "gdkinternals.h"
34 #include "gdkprivate-win32.h"
36 static void free_colormap (Colormap colormap);
38 static gint gdk_colormap_match_color (GdkColormap *cmap,
40 const gchar *available);
41 static void gdk_colormap_add (GdkColormap *cmap);
42 static void gdk_colormap_remove (GdkColormap *cmap);
43 static guint gdk_colormap_hash (Colormap *cmap);
44 static gboolean gdk_colormap_equal (Colormap *a,
47 static void gdk_colormap_init (GdkColormap *colormap);
48 static void gdk_colormap_class_init (GdkColormapClass *klass);
49 static void gdk_colormap_finalize (GObject *object);
51 static gpointer parent_class = NULL;
53 static GHashTable *colormap_hash = NULL;
56 gdk_colormap_get_type (void)
58 static GType object_type = 0;
62 static const GTypeInfo object_info =
64 sizeof (GdkColormapClass),
66 (GBaseFinalizeFunc) NULL,
67 (GClassInitFunc) gdk_colormap_class_init,
68 NULL, /* class_finalize */
69 NULL, /* class_data */
72 (GInstanceInitFunc) gdk_colormap_init,
75 object_type = g_type_register_static (G_TYPE_OBJECT,
84 gdk_colormap_init (GdkColormap *colormap)
86 GdkColormapPrivateWin32 *private;
88 private = g_new (GdkColormapPrivateWin32, 1);
90 colormap->windowing_data = private;
93 private->last_sync_time = 0;
97 colormap->colors = NULL;
101 gdk_colormap_class_init (GdkColormapClass *klass)
103 GObjectClass *object_class = G_OBJECT_CLASS (klass);
105 parent_class = g_type_class_peek_parent (klass);
107 object_class->finalize = gdk_colormap_finalize;
111 gdk_colormap_finalize (GObject *object)
113 GdkColormap *colormap = GDK_COLORMAP (object);
114 GdkColormapPrivateWin32 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
116 gdk_colormap_remove (colormap);
118 free_colormap (private->xcolormap);
121 g_hash_table_destroy (private->hash);
123 g_free (private->info);
124 g_free (colormap->colors);
126 G_OBJECT_CLASS (parent_class)->finalize (object);
130 alloc_color_cells(Colormap colormap,
132 unsigned long plane_masks_return[],
133 unsigned int nplanes,
134 unsigned long pixels_return[],
135 unsigned int npixels)
137 unsigned int i, nfree, iret;
140 for (i = 0; i < colormap->size && nfree < npixels; i++)
141 if (!colormap->in_use[i])
144 if (colormap->size + npixels - nfree > colormap->sizepalette)
146 g_warning ("alloc_color_cells: too large palette: %d",
147 colormap->size + npixels);
152 for (i = 0; i < colormap->size && iret < npixels; i++)
153 if (!colormap->in_use[i])
155 colormap->in_use[i] = TRUE;
156 pixels_return[iret] = i;
162 int nmore = npixels - nfree;
164 /* I don't understand why, if the code below in #if 0 is
165 enabled, gdkrgb fails miserably. The palette doesn't get
166 realized correctly. There doesn't seem to be any harm done by
167 keeping this code out, either. */
168 #ifdef SOME_STRANGE_BUG
169 if (!ResizePalette (colormap->palette, colormap->size + nmore))
171 WIN32_GDI_FAILED ("ResizePalette")
174 g_print("alloc_color_cells: %#x to %d\n",
175 colormap->palette, colormap->size + nmore);
177 for (i = colormap->size; i < colormap->size + nmore; i++)
179 pixels_return[iret] = i;
181 colormap->in_use[i] = TRUE;
183 #ifdef SOME_STRANGE_BUG
184 colormap->size += nmore;
190 /* The following functions are from Tk8.0, but heavily modified.
191 Here are tk's licensing terms. I hope these terms don't conflict
192 with the GNU Lesser General Public License? They shouldn't, as
193 they are looser that the GLPL, yes? */
196 This software is copyrighted by the Regents of the University of
197 California, Sun Microsystems, Inc., and other parties. The following
198 terms apply to all files associated with the software unless explicitly
199 disclaimed in individual files.
201 The authors hereby grant permission to use, copy, modify, distribute,
202 and license this software and its documentation for any purpose, provided
203 that existing copyright notices are retained in all copies and that this
204 notice is included verbatim in any distributions. No written agreement,
205 license, or royalty fee is required for any of the authorized uses.
206 Modifications to this software may be copyrighted by their authors
207 and need not follow the licensing terms described here, provided that
208 the new terms are clearly indicated on the first page of each file where
211 IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
212 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
213 ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
214 DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
215 POSSIBILITY OF SUCH DAMAGE.
217 THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
218 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
219 FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
220 IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
221 NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
224 GOVERNMENT USE: If you are acquiring this software on behalf of the
225 U.S. government, the Government shall have only "Restricted Rights"
226 in the software and related documentation as defined in the Federal
227 Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
228 are acquiring the software on behalf of the Department of Defense, the
229 software shall be classified as "Commercial Computer Software" and the
230 Government shall have only "Restricted Rights" as defined in Clause
231 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
232 authors grant the U.S. Government and others acting in its behalf
233 permission to use and distribute the software in accordance with the
234 terms specified in this license.
237 *----------------------------------------------------------------------
241 * Find the closest available color to the specified XColor.
244 * Updates the color argument and returns 1 on success. Otherwise
248 * Allocates a new color in the palette.
250 *----------------------------------------------------------------------
254 alloc_color(Colormap colormap,
258 PALETTEENTRY entry, closeEntry;
264 if (colormap->rc_palette)
266 COLORREF newPixel, closePixel;
270 * Find the nearest existing palette entry.
273 newPixel = RGB (entry.peRed, entry.peGreen, entry.peBlue);
274 index = GetNearestPaletteIndex (colormap->palette, newPixel);
275 GetPaletteEntries (colormap->palette, index, 1, &closeEntry);
276 closePixel = RGB (closeEntry.peRed, closeEntry.peGreen,
279 if (newPixel != closePixel)
281 /* Not a perfect match. */
282 if (!colormap->in_use[index])
284 /* It was a free'd entry anyway, so we can use it, and
285 set it to the correct color. */
286 if (SetPaletteEntries (colormap->palette, index, 1, &entry) == 0)
287 WIN32_GDI_FAILED ("SetPaletteEntries");
291 /* The close entry found is in use, so search for a
294 for (i = 0; i < colormap->size; i++)
295 if (!colormap->in_use[i])
297 /* A free slot, use it. */
298 if (SetPaletteEntries (colormap->palette,
299 index, 1, &entry) == 0)
300 WIN32_GDI_FAILED ("SetPaletteEntries");
304 if (i == colormap->size)
306 /* No free slots found. If the palette isn't maximal
308 if (colormap->size == colormap->sizepalette)
310 /* The palette is maximal, and no free slots available,
311 so use the close entry, then, dammit. */
316 /* There is room to grow the palette. */
317 index = colormap->size;
319 if (!ResizePalette (colormap->palette, colormap->size))
320 WIN32_GDI_FAILED ("ResizePalette");
321 if (SetPaletteEntries (colormap->palette, index, 1, &entry) == 0)
322 WIN32_GDI_FAILED ("SetPaletteEntries");
326 colormap->stale = TRUE;
330 /* We got a match, so use it. */
334 colormap->in_use[index] = TRUE;
336 g_print("alloc_color from %#x: index %d for %02x %02x %02x\n",
337 colormap->palette, index,
338 entry.peRed, entry.peGreen, entry.peBlue);
344 * Determine what color will actually be used on non-colormap systems.
346 *pixelp = GetNearestColor (gdk_display_hdc, RGB(entry.peRed, entry.peGreen, entry.peBlue));
348 color->peRed = GetRValue (*pixelp);
349 color->peGreen = GetGValue (*pixelp);
350 color->peBlue = GetBValue (*pixelp);
357 *----------------------------------------------------------------------
361 * Deallocate a block of colors.
367 * Removes entries for the current palette and compacts the
370 *----------------------------------------------------------------------
374 free_colors (Colormap colormap,
380 PALETTEENTRY entries[256];
383 * We don't have to do anything for non-palette devices.
386 if (colormap->rc_palette)
389 int lowestpixel = 256;
390 int highestpixel = -1;
392 npal = GetPaletteEntries (colormap->palette, 0, 256, entries);
393 for (i = 0; i < npixels; i++)
395 int pixel = pixels[i];
397 if (pixel < lowestpixel)
399 if (pixel > highestpixel)
400 highestpixel = pixel;
402 colormap->in_use[pixel] = FALSE;
404 entries[pixel] = entries[0];
407 if (SetPaletteEntries (colormap->palette, lowestpixel,
408 highestpixel - lowestpixel + 1,
409 entries + lowestpixel) == 0)
410 WIN32_GDI_FAILED ("SetPaletteEntries");
412 colormap->stale = TRUE;
414 g_print("free_colors %#x lowestpixel = %d, highestpixel = %d\n",
415 colormap->palette, lowestpixel, highestpixel);
421 *----------------------------------------------------------------------
425 * Allocate a new colormap.
428 * Returns a newly allocated colormap.
431 * Allocates an empty palette and color list.
433 *----------------------------------------------------------------------
437 create_colormap (HWND w,
441 char logPalBuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];
442 LOGPALETTE *logPalettePtr;
448 /* Should the alloc parameter do something? */
451 /* Allocate a starting palette with all of the reserved colors. */
453 logPalettePtr = (LOGPALETTE *) logPalBuf;
454 logPalettePtr->palVersion = 0x300;
455 sysPal = (HPALETTE) GetStockObject (DEFAULT_PALETTE);
456 logPalettePtr->palNumEntries =
457 GetPaletteEntries (sysPal, 0, 256, logPalettePtr->palPalEntry);
459 colormap = (Colormap) g_new (ColormapStruct, 1);
460 colormap->size = logPalettePtr->palNumEntries;
461 colormap->stale = TRUE;
462 colormap->palette = CreatePalette (logPalettePtr);
464 colormap->rc_palette = ((GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE) != 0);
465 if (colormap->rc_palette)
467 colormap->sizepalette = GetDeviceCaps (hdc, SIZEPALETTE);
468 colormap->in_use = g_new (gboolean, colormap->sizepalette);
469 /* Mark static colors in use. */
470 for (i = 0; i < logPalettePtr->palNumEntries; i++)
471 colormap->in_use[i] = TRUE;
472 /* Mark rest not in use */
473 for (i = logPalettePtr->palNumEntries; i < colormap->sizepalette; i++)
474 colormap->in_use[i] = FALSE;
476 ReleaseDC (NULL, hdc);
482 *----------------------------------------------------------------------
486 * Frees the resources associated with the given colormap.
492 * Deletes the palette associated with the colormap. Note that
493 * the palette must not be selected into a device context when
496 *----------------------------------------------------------------------
500 free_colormap(Colormap colormap)
503 if (!DeleteObject (colormap->palette))
505 g_error ("Unable to free colormap, palette is still selected.");
513 static Colormap colormap;
518 colormap = create_colormap ( NULL, NULL, FALSE);
523 gdk_colormap_new (GdkVisual *visual,
524 gboolean private_cmap)
526 GdkColormap *colormap;
527 GdkColormapPrivateWin32 *private;
531 g_return_val_if_fail (visual != NULL, NULL);
533 colormap = g_object_new (gdk_colormap_get_type (), NULL);
534 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
536 colormap->visual = visual;
538 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
540 colormap->size = visual->colormap_size;
542 switch (visual->type)
544 case GDK_VISUAL_GRAYSCALE:
545 case GDK_VISUAL_PSEUDO_COLOR:
546 private->info = g_new0 (GdkColorInfo, colormap->size);
547 colormap->colors = g_new (GdkColor, colormap->size);
549 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
550 (GEqualFunc) gdk_color_equal);
552 private->private_val = private_cmap;
553 private->xcolormap = create_colormap (gdk_root_window, xvisual, private_cmap);
557 PALETTEENTRY pal[256];
560 npal = GetPaletteEntries (private->xcolormap->palette, 0, colormap->size, pal);
561 for (i = 0; i < colormap->size; i++)
563 colormap->colors[i].pixel = i;
566 colormap->colors[i].red =
567 colormap->colors[i].green =
568 colormap->colors[i].blue = 0;
572 colormap->colors[i].red = (pal[i].peRed * 65535) / 255;
573 colormap->colors[i].green = (pal[i].peGreen * 65525) / 255;
574 colormap->colors[i].blue = (pal[i].peBlue * 65535) / 255;
577 gdk_colormap_change (colormap, colormap->size);
581 case GDK_VISUAL_STATIC_GRAY:
582 case GDK_VISUAL_STATIC_COLOR:
583 case GDK_VISUAL_TRUE_COLOR:
584 private->private_val = FALSE;
585 private->xcolormap = create_colormap (gdk_root_window,
589 case GDK_VISUAL_DIRECT_COLOR:
590 g_assert_not_reached ();
593 gdk_colormap_add (colormap);
598 #define MIN_SYNC_TIME 2
601 gdk_colormap_sync (GdkColormap *colormap,
605 GdkColormapPrivateWin32 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
610 g_return_if_fail (colormap != NULL);
612 current_time = time (NULL);
613 if (!force && ((current_time - private->last_sync_time) < MIN_SYNC_TIME))
616 private->last_sync_time = current_time;
619 xpalette = g_new (XColor, colormap->size);
621 nlookup = GetPaletteEntries (private->xcolormap->palette,
622 0, colormap->size, xpalette);
624 for (i = 0; i < nlookup; i++)
626 colormap->colors[i].pixel = i;
627 colormap->colors[i].red = (xpalette[i].peRed * 65535) / 255;
628 colormap->colors[i].green = (xpalette[i].peGreen * 65535) / 255;
629 colormap->colors[i].blue = (xpalette[i].peBlue * 65535) / 255;
632 for ( ; i < colormap->size; i++)
634 colormap->colors[i].pixel = i;
635 colormap->colors[i].red = 0;
636 colormap->colors[i].green = 0;
637 colormap->colors[i].blue = 0;
644 gdk_colormap_get_system (void)
646 static GdkColormap *colormap = NULL;
647 GdkColormapPrivateWin32 *private;
651 colormap = g_object_new (gdk_colormap_get_type (), NULL);
652 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
654 private->xcolormap = default_colormap ();
655 colormap->visual = gdk_visual_get_system ();
656 private->private_val = FALSE;
658 private->hash = NULL;
659 private->last_sync_time = 0;
660 private->info = NULL;
662 colormap->colors = NULL;
663 colormap->size = colormap->visual->colormap_size;
665 if ((colormap->visual->type == GDK_VISUAL_GRAYSCALE) ||
666 (colormap->visual->type == GDK_VISUAL_PSEUDO_COLOR))
668 private->info = g_new0 (GdkColorInfo, colormap->size);
669 colormap->colors = g_new (GdkColor, colormap->size);
671 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
672 (GEqualFunc) gdk_color_equal);
674 gdk_colormap_sync (colormap, TRUE);
676 gdk_colormap_add (colormap);
683 gdk_colormap_get_system_size (void)
687 bitspixel = GetDeviceCaps (gdk_display_hdc, BITSPIXEL);
691 else if (bitspixel == 4)
693 else if (bitspixel == 8)
695 else if (bitspixel == 12)
697 else if (bitspixel == 16)
699 else /* if (bitspixel >= 24) */
704 gdk_colormap_change (GdkColormap *colormap,
707 GdkColormapPrivateWin32 *private;
711 g_return_if_fail (GDK_IS_COLORMAP (colormap));
713 palette = g_new (XColor, ncolors);
715 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
716 switch (colormap->visual->type)
718 case GDK_VISUAL_GRAYSCALE:
719 case GDK_VISUAL_PSEUDO_COLOR:
720 for (i = 0; i < ncolors; i++)
722 palette[i].peRed = (colormap->colors[i].red >> 8);
723 palette[i].peGreen = (colormap->colors[i].green >> 8);
724 palette[i].peBlue = (colormap->colors[i].blue >> 8);
725 palette[i].peFlags = 0;
728 if (SetPaletteEntries (private->xcolormap->palette,
729 0, ncolors, palette) == 0)
730 WIN32_GDI_FAILED ("SetPaletteEntries");
731 private->xcolormap->stale = TRUE;
742 gdk_colors_alloc (GdkColormap *colormap,
749 GdkColormapPrivateWin32 *private;
753 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), 0);
755 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
757 return_val = alloc_color_cells (private->xcolormap, contiguous,
758 planes, nplanes, pixels, npixels);
762 for (i=0; i<npixels; i++)
764 private->info[pixels[i]].ref_count++;
765 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
769 return return_val != 0;
772 /* This is almost identical to gdk_colormap_free_colors.
776 gdk_colors_free (GdkColormap *colormap,
781 GdkColormapPrivateWin32 *private;
786 g_return_if_fail (GDK_IS_COLORMAP (colormap));
787 g_return_if_fail (in_pixels != NULL);
789 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
791 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
792 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
795 pixels = g_new (gulong, in_npixels);
797 for (i=0; i<in_npixels; i++)
799 gulong pixel = in_pixels[i];
801 if (private->info[pixel].ref_count)
803 private->info[pixel].ref_count--;
805 if (private->info[pixel].ref_count == 0)
807 pixels[npixels++] = pixel;
808 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
809 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
810 private->info[pixel].flags = 0;
816 free_colors (private->xcolormap, pixels, npixels, planes);
821 /* This is almost identical to gdk_colors_free.
825 gdk_colormap_free_colors (GdkColormap *colormap,
829 GdkColormapPrivateWin32 *private;
834 g_return_if_fail (GDK_IS_COLORMAP (colormap));
835 g_return_if_fail (colors != NULL);
837 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
839 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
840 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
843 pixels = g_new (gulong, ncolors);
845 for (i=0; i<ncolors; i++)
847 gulong pixel = colors[i].pixel;
849 if (private->info[pixel].ref_count)
851 private->info[pixel].ref_count--;
853 if (private->info[pixel].ref_count == 0)
855 pixels[npixels++] = pixel;
856 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
857 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
858 private->info[pixel].flags = 0;
863 free_colors (private->xcolormap, pixels, npixels, 0);
867 /********************
869 ********************/
871 /* Try to allocate a single color using alloc_color. If it succeeds,
872 * cache the result in our colormap, and store in ret.
875 gdk_colormap_alloc1 (GdkColormap *colormap,
879 GdkColormapPrivateWin32 *private;
882 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
884 xcolor.peRed = color->red >> 8;
885 xcolor.peGreen = color->green >> 8;
886 xcolor.peBlue = color->blue >> 8;
888 if (alloc_color (private->xcolormap, &xcolor, &ret->pixel))
890 ret->red = (xcolor.peRed * 65535) / 255;
891 ret->green = (xcolor.peGreen * 65535) / 255;
892 ret->blue = (xcolor.peBlue * 65535) / 255;
894 if ((guint) ret->pixel < colormap->size)
896 if (private->info[ret->pixel].ref_count) /* got a duplicate */
902 colormap->colors[ret->pixel] = *color;
903 private->info[ret->pixel].ref_count = 1;
905 g_hash_table_insert (private->hash,
906 &colormap->colors[ret->pixel],
907 &colormap->colors[ret->pixel]);
919 gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
926 GdkColormapPrivateWin32 *private;
931 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
933 if (private->private_val)
936 for (i=0; i<ncolors; i++)
938 while ((index < colormap->size) && (private->info[index].ref_count != 0))
941 if (index < colormap->size)
943 colors[i].pixel = index;
945 private->info[index].ref_count++;
946 private->info[i].flags |= GDK_COLOR_WRITEABLE;
955 pixels = g_new (gulong, ncolors);
956 /* Allocation of a writeable color cells */
958 status = alloc_color_cells (private->xcolormap, FALSE, NULL,
962 for (i=0; i<ncolors; i++)
964 colors[i].pixel = pixels[i];
965 private->info[pixels[i]].ref_count++;
966 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
972 return status ? ncolors : 0;
977 gdk_colormap_alloc_colors_private (GdkColormap *colormap,
984 GdkColormapPrivateWin32 *private;
986 XColor *store = g_new (XColor, ncolors);
990 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
993 /* First, store the colors we have room for */
996 for (i=0; i<ncolors; i++)
1000 while ((index < colormap->size) && (private->info[index].ref_count != 0))
1003 if (index < colormap->size)
1005 store[nstore].peRed = colors[i].red >> 8;
1006 store[nstore].peBlue = colors[i].blue >> 8;
1007 store[nstore].peGreen = colors[i].green >> 8;
1012 colors[i].pixel = index;
1013 private->info[index].ref_count++;
1020 if (SetPaletteEntries (private->xcolormap->palette,
1021 0, nstore, store) == 0)
1022 WIN32_GDI_FAILED ("SetPaletteEntries");
1023 private->xcolormap->stale = TRUE;
1027 if (nremaining > 0 && best_match)
1029 /* Get best matches for remaining colors */
1031 gchar *available = g_new (gchar, colormap->size);
1032 for (i = 0; i < colormap->size; i++)
1033 available[i] = TRUE;
1035 for (i=0; i<ncolors; i++)
1039 index = gdk_colormap_match_color (colormap,
1044 colors[i] = colormap->colors[index];
1045 private->info[index].ref_count++;
1055 return (ncolors - nremaining);
1059 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
1063 gboolean best_match,
1066 GdkColormapPrivateWin32 *private;
1068 gint nremaining = 0;
1071 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1074 for (i=0; i<ncolors; i++)
1078 if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
1086 if (nremaining > 0 && best_match)
1088 gchar *available = g_new (gchar, colormap->size);
1089 for (i = 0; i < colormap->size; i++)
1090 available[i] = ((private->info[i].ref_count == 0) ||
1091 !(private->info[i].flags & GDK_COLOR_WRITEABLE));
1092 gdk_colormap_sync (colormap, FALSE);
1094 while (nremaining > 0)
1096 for (i=0; i<ncolors; i++)
1100 index = gdk_colormap_match_color (colormap, &colors[i], available);
1103 if (private->info[index].ref_count)
1105 private->info[index].ref_count++;
1106 colors[i] = colormap->colors[index];
1112 if (gdk_colormap_alloc1 (colormap,
1113 &colormap->colors[index],
1122 available[index] = FALSE;
1130 success[i] = 2; /* flag as permanent failure */
1138 /* Change back the values we flagged as permanent failures */
1141 for (i=0; i<ncolors; i++)
1142 if (success[i] == 2)
1144 nremaining = nfailed;
1147 return (ncolors - nremaining);
1151 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
1155 gboolean best_match,
1158 GdkColormapPrivateWin32 *private;
1159 GdkColor *lookup_color;
1161 gint nremaining = 0;
1163 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1165 /* Check for an exact match among previously allocated colors */
1167 for (i=0; i<ncolors; i++)
1171 lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
1174 private->info[lookup_color->pixel].ref_count++;
1175 colors[i].pixel = lookup_color->pixel;
1183 /* If that failed, we try to allocate a new color, or approxmiate
1184 * with what we can get if best_match is TRUE.
1188 if (private->private_val)
1189 return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
1191 return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
1198 gdk_colormap_alloc_colors (GdkColormap *colormap,
1202 gboolean best_match,
1205 GdkColormapPrivateWin32 *private;
1208 gint nremaining = 0;
1211 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1212 g_return_val_if_fail (colors != NULL, FALSE);
1214 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1216 for (i=0; i<ncolors; i++)
1221 switch (colormap->visual->type)
1223 case GDK_VISUAL_PSEUDO_COLOR:
1224 case GDK_VISUAL_GRAYSCALE:
1226 return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
1227 writeable, best_match, success);
1229 return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
1230 writeable, best_match, success);
1233 case GDK_VISUAL_TRUE_COLOR:
1234 visual = colormap->visual;
1236 for (i=0; i<ncolors; i++)
1238 colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
1239 ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
1240 ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
1245 case GDK_VISUAL_STATIC_GRAY:
1246 case GDK_VISUAL_STATIC_COLOR:
1247 for (i=0; i<ncolors; i++)
1249 xcolor.peRed = colors[i].red >> 8;
1250 xcolor.peGreen = colors[i].green >> 8;
1251 xcolor.peBlue = colors[i].blue >> 8;
1252 if (alloc_color (private->xcolormap, &xcolor, &colors[i].pixel))
1259 case GDK_VISUAL_DIRECT_COLOR:
1260 g_assert_not_reached ();
1266 gdk_colormap_query_color (GdkColormap *colormap,
1272 g_return_if_fail (GDK_IS_COLORMAP (colormap));
1274 visual = gdk_colormap_get_visual (colormap);
1276 switch (visual->type) {
1277 case GDK_VISUAL_DIRECT_COLOR:
1278 case GDK_VISUAL_TRUE_COLOR:
1279 result->red = 65535. * (double)((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
1280 result->green = 65535. * (double)((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
1281 result->blue = 65535. * (double)((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
1283 case GDK_VISUAL_STATIC_GRAY:
1284 case GDK_VISUAL_GRAYSCALE:
1285 result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
1287 case GDK_VISUAL_STATIC_COLOR:
1288 g_assert_not_reached ();
1290 case GDK_VISUAL_PSEUDO_COLOR:
1291 result->red = colormap->colors[pixel].red;
1292 result->green = colormap->colors[pixel].green;
1293 result->blue = colormap->colors[pixel].blue;
1296 g_assert_not_reached ();
1302 gdk_color_change (GdkColormap *colormap,
1305 GdkColormapPrivateWin32 *private;
1308 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1309 g_return_val_if_fail (color != NULL, FALSE);
1311 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1313 xcolor.peRed = color->red >> 8;
1314 xcolor.peGreen = color->green >> 8;
1315 xcolor.peBlue = color->blue >> 8;
1317 if (SetPaletteEntries (private->xcolormap->palette,
1318 color->pixel, 1, &xcolor) == 0)
1319 WIN32_GDI_FAILED ("SetPaletteEntries");
1320 private->xcolormap->stale = TRUE;
1326 gdk_colormap_match_color (GdkColormap *cmap,
1328 const gchar *available)
1332 gint rdiff, gdiff, bdiff;
1335 g_return_val_if_fail (cmap != NULL, 0);
1336 g_return_val_if_fail (color != NULL, 0);
1338 colors = cmap->colors;
1342 for (i = 0; i < cmap->size; i++)
1344 if ((!available) || (available && available[i]))
1346 rdiff = (color->red - colors[i].red);
1347 gdiff = (color->green - colors[i].green);
1348 bdiff = (color->blue - colors[i].blue);
1350 sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1364 gdk_colormap_lookup (Colormap xcolormap)
1371 cmap = g_hash_table_lookup (colormap_hash, &xcolormap);
1376 gdk_colormap_add (GdkColormap *cmap)
1378 GdkColormapPrivateWin32 *private;
1381 colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
1382 (GEqualFunc) gdk_colormap_equal);
1384 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1386 g_hash_table_insert (colormap_hash, &private->xcolormap, cmap);
1390 gdk_colormap_remove (GdkColormap *cmap)
1392 GdkColormapPrivateWin32 *private;
1395 colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
1396 (GEqualFunc) gdk_colormap_equal);
1398 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1400 g_hash_table_remove (colormap_hash, &private->xcolormap);
1404 gdk_colormap_hash (Colormap *cmap)
1406 return (guint) *cmap;
1410 gdk_colormap_equal (Colormap *a,
1416 #ifdef G_ENABLE_DEBUG
1419 gdk_win32_color_to_string (const GdkColor *color)
1421 static char buf[100];
1423 sprintf (buf, "(%.04x,%.04x,%.04x):%.06x",
1424 color->red, color->green, color->blue, color->pixel);