1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * Copyright (C) 1998-2002 Tor Lillqvist
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
33 #include "gdkscreen.h"
34 #include "gdkinternals.h"
35 #include "gdkprivate-win32.h"
37 static gint gdk_colormap_match_color (GdkColormap *cmap,
39 const gchar *available);
40 static void gdk_colormap_init (GdkColormap *colormap);
41 static void gdk_colormap_class_init (GdkColormapClass *klass);
42 static void gdk_colormap_finalize (GObject *object);
44 static gpointer parent_class = NULL;
47 gdk_colormap_get_type (void)
49 static GType object_type = 0;
53 static const GTypeInfo object_info =
55 sizeof (GdkColormapClass),
57 (GBaseFinalizeFunc) NULL,
58 (GClassInitFunc) gdk_colormap_class_init,
59 NULL, /* class_finalize */
60 NULL, /* class_data */
63 (GInstanceInitFunc) gdk_colormap_init,
66 object_type = g_type_register_static (G_TYPE_OBJECT,
75 gdk_colormap_init (GdkColormap *colormap)
77 GdkColormapPrivateWin32 *private;
79 private = g_new (GdkColormapPrivateWin32, 1);
81 colormap->windowing_data = private;
84 private->current_size = 0;
90 colormap->colors = NULL;
94 gdk_colormap_class_init (GdkColormapClass *klass)
96 GObjectClass *object_class = G_OBJECT_CLASS (klass);
98 parent_class = g_type_class_peek_parent (klass);
100 object_class->finalize = gdk_colormap_finalize;
104 gdk_colormap_finalize (GObject *object)
106 GdkColormap *colormap = GDK_COLORMAP (object);
107 GdkColormapPrivateWin32 *private = GDK_WIN32_COLORMAP_DATA (colormap);
109 if (!DeleteObject (private->hpal))
110 WIN32_GDI_FAILED ("DeleteObject");
113 g_hash_table_destroy (private->hash);
115 g_free (private->info);
116 g_free (colormap->colors);
118 G_OBJECT_CLASS (parent_class)->finalize (object);
121 /* Mimics XAllocColorCells. Allocate read/write color cells. */
124 alloc_color_cells (GdkColormap *cmap,
126 unsigned long plane_masks_return[],
127 unsigned int nplanes,
128 unsigned long pixels_return[],
129 unsigned int npixels)
131 GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
132 gint i, nfree, iret, start = 0;
134 GDK_NOTE (COLORMAP, g_print ("alloc_color_cells: cmap=%p contig=%s npl=%d npix=%d",
135 cmapp, contig ? "TRUE" : "FALSE",
138 switch (cmap->visual->type)
140 case GDK_VISUAL_GRAYSCALE:
141 case GDK_VISUAL_PSEUDO_COLOR:
143 for (i = 0; i < cmap->size && nfree < npixels; i++)
144 if (cmapp->use[i] == GDK_WIN32_PE_AVAILABLE &&
146 (nfree == 0 || cmapp->use[i-1] == GDK_WIN32_PE_AVAILABLE)))
157 GDK_NOTE (COLORMAP, g_print ("...nope (%d > %d)\n", npixels, nfree));
161 GDK_NOTE (COLORMAP, g_print ("...ok\n"));
164 for (i = start; i < cmap->size && iret < npixels; i++)
165 if (cmapp->use[i] == GDK_WIN32_PE_AVAILABLE)
167 cmapp->use[i] = GDK_WIN32_PE_INUSE;
168 pixels_return[iret] = i;
171 g_assert (iret == npixels);
175 g_assert_not_reached ();
181 /* The following functions are originally from Tk8.0, but heavily
182 modified. Here are tk's licensing terms. I hope these terms don't
183 conflict with the GNU Lesser General Public License? They
184 shouldn't, as they are looser that the GLPL, yes? */
187 This software is copyrighted by the Regents of the University of
188 California, Sun Microsystems, Inc., and other parties. The following
189 terms apply to all files associated with the software unless explicitly
190 disclaimed in individual files.
192 The authors hereby grant permission to use, copy, modify, distribute,
193 and license this software and its documentation for any purpose, provided
194 that existing copyright notices are retained in all copies and that this
195 notice is included verbatim in any distributions. No written agreement,
196 license, or royalty fee is required for any of the authorized uses.
197 Modifications to this software may be copyrighted by their authors
198 and need not follow the licensing terms described here, provided that
199 the new terms are clearly indicated on the first page of each file where
202 IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
203 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
204 ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
205 DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
206 POSSIBILITY OF SUCH DAMAGE.
208 THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
209 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
210 FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
211 IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
212 NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
215 GOVERNMENT USE: If you are acquiring this software on behalf of the
216 U.S. government, the Government shall have only "Restricted Rights"
217 in the software and related documentation as defined in the Federal
218 Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
219 are acquiring the software on behalf of the Department of Defense, the
220 software shall be classified as "Commercial Computer Software" and the
221 Government shall have only "Restricted Rights" as defined in Clause
222 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
223 authors grant the U.S. Government and others acting in its behalf
224 permission to use and distribute the software in accordance with the
225 terms specified in this license.
228 /* Mimics XAllocColor. Allocate a read-only colormap entry. */
231 alloc_color (GdkColormap *cmap,
235 PALETTEENTRY entry, close_entry;
238 GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
244 new_pixel = RGB (entry.peRed, entry.peGreen, entry.peBlue);
246 switch (cmap->visual->type)
248 case GDK_VISUAL_PSEUDO_COLOR:
249 /* Find the nearest existing palette entry. */
250 index = GetNearestPaletteIndex (cmapp->hpal, new_pixel);
251 GetPaletteEntries (cmapp->hpal, index, 1, &close_entry);
254 g_print ("alloc_color: new_pixel=%06lx index=%d=%02x close=%06lx\n",
255 new_pixel, index, index,
256 RGB (close_entry.peRed, close_entry.peGreen, close_entry.peBlue)));
258 if (new_pixel != RGB (close_entry.peRed, close_entry.peGreen,
261 /* Not a perfect match. */
262 if (cmapp->use[index] == GDK_WIN32_PE_AVAILABLE)
264 /* It was a nonused entry anyway, so we can use it, and
265 * set it to the correct color.
267 GDK_NOTE (COLORMAP, g_print ("...was free\n"));
268 if (!SetPaletteEntries (cmapp->hpal, index, 1, &entry))
269 WIN32_GDI_FAILED ("SetPaletteEntries");
273 /* The close entry found is in use, so search for a
276 gboolean done = FALSE;
277 for (i = 0; i < cmap->size; i++)
278 if (cmapp->use[i] == GDK_WIN32_PE_AVAILABLE)
280 /* An available slot, use it. */
282 g_print ("...use free slot %d%s\n",
283 i, (i >= cmapp->current_size) ?
284 ", will resize palette" : ""));
285 if (i >= cmapp->current_size)
287 if (!ResizePalette (cmapp->hpal, i + 1))
289 WIN32_GDI_FAILED ("ResizePalette");
292 cmapp->current_size = i + 1;
294 if (!SetPaletteEntries (cmapp->hpal, i, 1, &entry))
296 WIN32_GDI_FAILED ("SetPaletteEntries");
308 /* No free slots available, or failed to resize
309 * palette or set palette entry.
311 GDK_NOTE (COLORMAP, g_print ("... failure\n"));
318 /* We got a match, so use it. */
322 cmapp->use[index] = GDK_WIN32_PE_INUSE;
323 GDK_NOTE (COLORMAP, g_print ("alloc_color: %p: "
324 "index=%3d=%02x for %02x %02x %02x: "
326 cmapp->hpal, index, index,
327 entry.peRed, entry.peGreen, entry.peBlue,
328 color->peRed, color->peGreen, color->peBlue));
331 case GDK_VISUAL_STATIC_COLOR:
332 /* Find the nearest existing palette entry. */
333 index = GetNearestPaletteIndex (cmapp->hpal, new_pixel);
334 GetPaletteEntries (cmapp->hpal, index, 1, &close_entry);
335 *color = close_entry;
337 GDK_NOTE (COLORMAP, g_print ("alloc_color %p: "
338 "index=%3d=%02x for %02x %02x %02x: "
340 cmapp->hpal, index, index,
341 entry.peRed, entry.peGreen, entry.peBlue,
342 color->peRed, color->peGreen, color->peBlue));
345 case GDK_VISUAL_TRUE_COLOR:
346 /* Determine what color will actually be used on non-colormap systems. */
348 *pixelp = GetNearestColor (_gdk_display_hdc, new_pixel);
349 color->peRed = GetRValue (*pixelp);
350 color->peGreen = GetGValue (*pixelp);
351 color->peBlue = GetBValue (*pixelp);
355 g_assert_not_reached ();
360 /* Mimics XFreeColors. */
363 free_colors (GdkColormap *cmap,
369 GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
371 #ifdef G_ENABLE_DEBUG
372 gint set_black_count = 0;
374 gboolean *cleared_entries;
376 cleared_entries = g_new0 (gboolean, cmap->size);
378 /* We don't have to do anything for non-palette devices. */
380 switch (cmap->visual->type)
382 case GDK_VISUAL_GRAYSCALE:
383 case GDK_VISUAL_PSEUDO_COLOR:
384 for (i = 0; i < npixels; i++)
386 if (pixels[i] >= cmap->size)
388 else if (cmapp->use[pixels[i]] == GDK_WIN32_PE_STATIC)
389 ; /* Nothing either*/
392 cmapp->use[pixels[i]] = GDK_WIN32_PE_AVAILABLE;
393 cleared_entries[pixels[i]] = TRUE;
396 for (i = cmapp->current_size - 1; i >= 0; i--)
397 if (cmapp->use[i] != GDK_WIN32_PE_AVAILABLE)
399 if (i < cmapp->current_size - 1)
401 GDK_NOTE (COLORMAP, g_print ("free_colors: hpal=%p resize=%d\n",
402 cmapp->hpal, i + 1));
403 if (!ResizePalette (cmapp->hpal, i + 1))
404 WIN32_GDI_FAILED ("ResizePalette");
406 cmapp->current_size = i + 1;
408 pe.peRed = pe.peGreen = pe.peBlue = pe.peFlags = 0;
409 for (i = 0; i < cmapp->current_size; i++)
411 if (cleared_entries[i])
413 if (!SetPaletteEntries (cmapp->hpal, i, 1, &pe))
414 WIN32_GDI_FAILED ("SetPaletteEntries");
415 GDK_NOTE (COLORMAP, set_black_count++);
419 GDK_NOTE (COLORMAP, _gdk_win32_print_hpalette (cmapp->hpal));
421 GDK_NOTE (COLORMAP, (set_black_count > 0 ?
422 g_print ("free_colors: %d (%d) set to black\n",
423 set_black_count, cmapp->current_size)
426 g_free (cleared_entries);
431 g_assert_not_reached ();
435 /* Mimics XCreateColormap. */
438 create_colormap (GdkColormap *cmap,
443 PALETTEENTRY pe[256-1];
446 GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
449 /* Allocate a starting palette with all the static colors. */
450 hpal = GetStockObject (DEFAULT_PALETTE);
451 lp.pal.palVersion = 0x300;
452 lp.pal.palNumEntries = GetPaletteEntries (hpal, 0, 256, lp.pal.palPalEntry);
454 if (cmap->visual->type == GDK_VISUAL_STATIC_COLOR &&
455 cmap->visual->depth == 4)
457 /* Use only 16 colors */
458 for (i = 8; i < 16; i++)
459 lp.pal.palPalEntry[i] = lp.pal.palPalEntry[i+4];
460 lp.pal.palNumEntries = 16;
463 for (i = 0; i < lp.pal.palNumEntries; i++)
464 lp.pal.palPalEntry[i].peFlags = 0;
465 GDK_NOTE (COLORMAP, (g_print ("Default palette %p: %d entries\n",
466 hpal, lp.pal.palNumEntries),
467 _gdk_win32_print_paletteentries (lp.pal.palPalEntry,
468 lp.pal.palNumEntries)));
471 /* For writeable colormaps, allow all 256 entries to be set. They won't
472 * set all 256 system palette entries anyhow, of course, but we shouldn't
473 * let the app see that, I think.
476 cmapp->current_size = 0;
478 cmapp->current_size = lp.pal.palNumEntries;
480 cmapp->private_val = writeable;
482 if (!(cmapp->hpal = CreatePalette (&lp.pal)))
483 WIN32_GDI_FAILED ("CreatePalette");
485 GDK_NOTE (COLORMAP, g_print ("Created palette %p\n", cmapp->hpal));
487 switch (cmap->visual->type)
489 case GDK_VISUAL_PSEUDO_COLOR:
490 cmapp->use = g_new (GdkWin32PalEntryState, cmap->size);
492 /* Mark static colors in use. */
493 for (i = 0; i < cmapp->current_size; i++)
495 cmapp->use[i] = GDK_WIN32_PE_STATIC;
496 cmapp->info[i].ref_count = G_MAXUINT/2;
498 /* Mark rest not in use */
499 for (; i < cmap->size; i++)
500 cmapp->use[i] = GDK_WIN32_PE_AVAILABLE;
509 sync_colors (GdkColormap *colormap)
512 GdkColormapPrivateWin32 *private = GDK_WIN32_COLORMAP_DATA (colormap);
516 pe = g_new (PALETTEENTRY, colormap->size);
517 nlookup = GetPaletteEntries (private->hpal, 0, colormap->size, pe);
519 GDK_NOTE (COLORMAP, (g_print ("sync_colors: %p hpal=%p: %d entries\n",
520 private, private->hpal, nlookup),
521 _gdk_win32_print_paletteentries (pe, nlookup)));
523 for (i = 0; i < nlookup; i++)
525 colormap->colors[i].pixel = i;
526 colormap->colors[i].red = (pe[i].peRed * 65535) / 255;
527 colormap->colors[i].green = (pe[i].peGreen * 65535) / 255;
528 colormap->colors[i].blue = (pe[i].peBlue * 65535) / 255;
531 for ( ; i < colormap->size; i++)
533 colormap->colors[i].pixel = i;
534 colormap->colors[i].red = 0;
535 colormap->colors[i].green = 0;
536 colormap->colors[i].blue = 0;
543 gdk_colormap_new (GdkVisual *visual,
544 gboolean private_cmap)
546 GdkColormap *colormap;
547 GdkColormapPrivateWin32 *private;
549 g_return_val_if_fail (visual != NULL, NULL);
551 colormap = g_object_new (gdk_colormap_get_type (), NULL);
552 private = GDK_WIN32_COLORMAP_DATA (colormap);
554 colormap->visual = visual;
556 colormap->size = visual->colormap_size;
558 switch (visual->type)
560 case GDK_VISUAL_GRAYSCALE:
561 case GDK_VISUAL_PSEUDO_COLOR:
562 private->info = g_new0 (GdkColorInfo, colormap->size);
563 colormap->colors = g_new (GdkColor, colormap->size);
565 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
566 (GEqualFunc) gdk_color_equal);
568 create_colormap (colormap, private_cmap);
572 sync_colors (colormap);
573 #if 0 /* XXX is this needed or not? Seems redundant */
574 gdk_colormap_change (colormap, colormap->size);
579 case GDK_VISUAL_STATIC_GRAY:
580 case GDK_VISUAL_STATIC_COLOR:
581 create_colormap (colormap, FALSE);
582 colormap->colors = g_new (GdkColor, colormap->size);
583 sync_colors (colormap);
586 case GDK_VISUAL_TRUE_COLOR:
590 g_assert_not_reached ();
597 gdk_screen_get_system_colormap (GdkScreen *screen)
599 static GdkColormap *colormap = NULL;
600 GdkColormapPrivateWin32 *private;
604 colormap = g_object_new (gdk_colormap_get_type (), NULL);
605 private = GDK_WIN32_COLORMAP_DATA (colormap);
607 colormap->visual = gdk_visual_get_system ();
609 colormap->size = colormap->visual->colormap_size;
611 private->private_val = FALSE;
613 switch (colormap->visual->type)
615 case GDK_VISUAL_GRAYSCALE:
616 case GDK_VISUAL_PSEUDO_COLOR:
617 private->info = g_new0 (GdkColorInfo, colormap->size);
618 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
619 (GEqualFunc) gdk_color_equal);
622 case GDK_VISUAL_STATIC_GRAY:
623 case GDK_VISUAL_STATIC_COLOR:
624 create_colormap (colormap, FALSE);
626 colormap->colors = g_new (GdkColor, colormap->size);
627 sync_colors (colormap);
630 case GDK_VISUAL_TRUE_COLOR:
634 g_assert_not_reached ();
642 gdk_colormap_get_system_size (void)
644 return gdk_colormap_get_system ()->size;
648 gdk_colormap_change (GdkColormap *colormap,
651 GdkColormapPrivateWin32 *cmapp;
655 g_return_if_fail (colormap != NULL);
657 cmapp = GDK_WIN32_COLORMAP_DATA (colormap);
659 GDK_NOTE (COLORMAP, g_print ("gdk_colormap_change: hpal=%p ncolors=%d\n",
660 cmapp->hpal, ncolors));
662 switch (colormap->visual->type)
664 case GDK_VISUAL_GRAYSCALE:
665 case GDK_VISUAL_PSEUDO_COLOR:
666 pe = g_new (PALETTEENTRY, ncolors);
668 for (i = 0; i < ncolors; i++)
670 pe[i].peRed = (colormap->colors[i].red >> 8);
671 pe[i].peGreen = (colormap->colors[i].green >> 8);
672 pe[i].peBlue = (colormap->colors[i].blue >> 8);
676 if (!SetPaletteEntries (cmapp->hpal, 0, ncolors, pe))
677 WIN32_GDI_FAILED ("SetPaletteEntries");
687 gdk_colors_alloc (GdkColormap *colormap,
694 GdkColormapPrivateWin32 *private;
698 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), 0);
700 private = GDK_WIN32_COLORMAP_DATA (colormap);
702 return_val = alloc_color_cells (colormap, contiguous,
703 planes, nplanes, pixels, npixels);
707 for (i = 0; i < npixels; i++)
709 private->info[pixels[i]].ref_count++;
710 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
714 return return_val != 0;
718 gdk_colors_free (GdkColormap *colormap,
723 GdkColormapPrivateWin32 *private;
728 g_return_if_fail (GDK_IS_COLORMAP (colormap));
729 g_return_if_fail (in_pixels != NULL);
731 private = GDK_WIN32_COLORMAP_DATA (colormap);
733 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
734 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
737 pixels = g_new (gulong, in_npixels);
739 for (i = 0; i < in_npixels; i++)
741 gulong pixel = in_pixels[i];
743 if (private->use[pixel] == GDK_WIN32_PE_STATIC)
746 if (private->info[pixel].ref_count)
748 private->info[pixel].ref_count--;
750 if (private->info[pixel].ref_count == 0)
752 pixels[npixels++] = pixel;
753 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
754 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
755 private->info[pixel].flags = 0;
761 free_colors (colormap, pixels, npixels, planes);
767 gdk_colormap_free_colors (GdkColormap *colormap,
774 g_return_if_fail (GDK_IS_COLORMAP (colormap));
775 g_return_if_fail (colors != NULL);
777 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
778 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
781 pixels = g_new (gulong, ncolors);
783 for (i = 0; i < ncolors; i++)
784 pixels[i] = colors[i].pixel;
786 gdk_colors_free (colormap, pixels, ncolors, 0);
791 /********************
793 ********************/
795 /* Try to allocate a single color using alloc_color. If it succeeds,
796 * cache the result in our colormap, and store in ret.
799 gdk_colormap_alloc1 (GdkColormap *colormap,
803 GdkColormapPrivateWin32 *private;
806 private = GDK_WIN32_COLORMAP_DATA (colormap);
808 pe.peRed = color->red >> 8;
809 pe.peGreen = color->green >> 8;
810 pe.peBlue = color->blue >> 8;
812 if (alloc_color (colormap, &pe, &ret->pixel))
814 ret->red = (pe.peRed * 65535) / 255;
815 ret->green = (pe.peGreen * 65535) / 255;
816 ret->blue = (pe.peBlue * 65535) / 255;
818 if ((guint) ret->pixel < colormap->size)
820 if (private->info[ret->pixel].ref_count) /* got a duplicate */
825 colormap->colors[ret->pixel] = *color;
826 colormap->colors[ret->pixel].pixel = ret->pixel;
827 private->info[ret->pixel].ref_count = 1;
829 g_hash_table_insert (private->hash,
830 &colormap->colors[ret->pixel],
831 &colormap->colors[ret->pixel]);
840 gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
847 GdkColormapPrivateWin32 *private;
852 private = GDK_WIN32_COLORMAP_DATA (colormap);
854 if (private->private_val)
857 for (i=0; i<ncolors; i++)
859 while ((index < colormap->size) &&
860 (private->info[index].ref_count != 0))
863 if (index < colormap->size)
865 colors[i].pixel = index;
867 private->info[index].ref_count++;
868 private->info[i].flags |= GDK_COLOR_WRITEABLE;
877 pixels = g_new (gulong, ncolors);
879 /* Allocation of a writeable color cells */
880 status = alloc_color_cells (colormap, FALSE, NULL, 0, pixels, ncolors);
883 for (i = 0; i < ncolors; i++)
885 colors[i].pixel = pixels[i];
886 private->info[pixels[i]].ref_count++;
887 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
893 return status ? ncolors : 0;
898 gdk_colormap_alloc_colors_private (GdkColormap *colormap,
905 GdkColormapPrivateWin32 *cmapp;
910 cmapp = GDK_WIN32_COLORMAP_DATA (colormap);
913 /* First, store the colors we have room for */
916 for (i = 0; i < ncolors; i++)
920 while ((index < colormap->size) &&
921 (cmapp->info[index].ref_count != 0))
924 if (index < colormap->size)
926 if (index >= cmapp->current_size)
928 if (!ResizePalette (cmapp->hpal, index + 1))
930 WIN32_GDI_FAILED ("ResizePalette");
934 cmapp->current_size = index + 1;
936 if (index < cmapp->current_size)
938 pe.peRed = colors[i].red >> 8;
939 pe.peBlue = colors[i].blue >> 8;
940 pe.peGreen = colors[i].green >> 8;
943 if (!SetPaletteEntries (cmapp->hpal, index, 1, &pe))
945 WIN32_GDI_FAILED ("SetPaletteEntries");
952 colors[i].pixel = index;
953 colormap->colors[index] = colors[i];
954 cmapp->info[index].ref_count++;
963 if (nremaining > 0 && best_match)
965 /* Get best matches for remaining colors */
967 gchar *available = g_new (gchar, colormap->size);
968 for (i = 0; i < colormap->size; i++)
971 for (i=0; i<ncolors; i++)
975 index = gdk_colormap_match_color (colormap,
980 colors[i] = colormap->colors[index];
981 cmapp->info[index].ref_count++;
991 return (ncolors - nremaining);
995 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
1002 GdkColormapPrivateWin32 *private;
1004 gint nremaining = 0;
1007 private = GDK_WIN32_COLORMAP_DATA (colormap);
1010 for (i = 0; i < ncolors; i++)
1014 if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
1022 if (nremaining > 0 && best_match)
1024 gchar *available = g_new (gchar, colormap->size);
1025 for (i = 0; i < colormap->size; i++)
1026 available[i] = ((private->info[i].ref_count == 0) ||
1027 !(private->info[i].flags & GDK_COLOR_WRITEABLE));
1028 while (nremaining > 0)
1030 for (i = 0; i < ncolors; i++)
1034 index = gdk_colormap_match_color (colormap, &colors[i], available);
1037 if (private->info[index].ref_count)
1039 private->info[index].ref_count++;
1040 colors[i] = colormap->colors[index];
1046 if (gdk_colormap_alloc1 (colormap,
1047 &colormap->colors[index],
1056 available[index] = FALSE;
1064 success[i] = 2; /* flag as permanent failure */
1072 /* Change back the values we flagged as permanent failures */
1075 for (i = 0; i < ncolors; i++)
1076 if (success[i] == 2)
1078 nremaining = nfailed;
1081 return (ncolors - nremaining);
1085 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
1089 gboolean best_match,
1092 GdkColormapPrivateWin32 *private;
1093 GdkColor *lookup_color;
1095 gint nremaining = 0;
1097 private = GDK_WIN32_COLORMAP_DATA (colormap);
1099 /* Check for an exact match among previously allocated colors */
1101 for (i = 0; i < ncolors; i++)
1105 lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
1108 private->info[lookup_color->pixel].ref_count++;
1109 colors[i].pixel = lookup_color->pixel;
1117 /* If that failed, we try to allocate a new color, or approxmiate
1118 * with what we can get if best_match is TRUE.
1122 if (private->private_val)
1123 return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
1125 return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
1132 gdk_colormap_alloc_colors (GdkColormap *colormap,
1136 gboolean best_match,
1139 GdkColormapPrivateWin32 *private;
1142 gint nremaining = 0;
1145 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1146 g_return_val_if_fail (colors != NULL, FALSE);
1148 private = GDK_WIN32_COLORMAP_DATA (colormap);
1150 for (i = 0; i < ncolors; i++)
1153 switch (colormap->visual->type)
1155 case GDK_VISUAL_PSEUDO_COLOR:
1156 case GDK_VISUAL_GRAYSCALE:
1158 return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
1159 writeable, best_match, success);
1161 return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
1162 writeable, best_match, success);
1165 case GDK_VISUAL_TRUE_COLOR:
1166 visual = colormap->visual;
1168 for (i = 0; i < ncolors; i++)
1171 (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
1172 ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
1173 ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
1178 case GDK_VISUAL_STATIC_GRAY:
1179 case GDK_VISUAL_STATIC_COLOR:
1180 for (i = 0; i < ncolors; i++)
1182 pe.peRed = colors[i].red >> 8;
1183 pe.peGreen = colors[i].green >> 8;
1184 pe.peBlue = colors[i].blue >> 8;
1185 if (alloc_color (colormap, &pe, &colors[i].pixel))
1192 case GDK_VISUAL_DIRECT_COLOR:
1193 g_assert_not_reached ();
1200 gdk_colormap_query_color (GdkColormap *colormap,
1206 g_return_if_fail (GDK_IS_COLORMAP (colormap));
1208 visual = gdk_colormap_get_visual (colormap);
1210 switch (visual->type)
1212 case GDK_VISUAL_DIRECT_COLOR:
1213 case GDK_VISUAL_TRUE_COLOR:
1214 result->red = 65535. * (double)((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
1215 result->green = 65535. * (double)((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
1216 result->blue = 65535. * (double)((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
1219 case GDK_VISUAL_STATIC_GRAY:
1220 case GDK_VISUAL_GRAYSCALE:
1221 result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
1224 case GDK_VISUAL_STATIC_COLOR:
1225 case GDK_VISUAL_PSEUDO_COLOR:
1226 result->red = colormap->colors[pixel].red;
1227 result->green = colormap->colors[pixel].green;
1228 result->blue = colormap->colors[pixel].blue;
1232 g_assert_not_reached ();
1238 gdk_color_change (GdkColormap *colormap,
1241 GdkColormapPrivateWin32 *private;
1244 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1245 g_return_val_if_fail (color != NULL, FALSE);
1247 private = GDK_WIN32_COLORMAP_DATA (colormap);
1249 if (color->pixel < 0 || color->pixel >= colormap->size)
1252 if (private->use[color->pixel] == GDK_WIN32_PE_STATIC)
1255 pe.peRed = color->red >> 8;
1256 pe.peGreen = color->green >> 8;
1257 pe.peBlue = color->blue >> 8;
1259 if (SetPaletteEntries (private->hpal, color->pixel, 1, &pe) == 0)
1260 WIN32_GDI_FAILED ("SetPaletteEntries");
1266 gdk_colormap_match_color (GdkColormap *cmap,
1268 const gchar *available)
1272 gint rdiff, gdiff, bdiff;
1275 g_return_val_if_fail (cmap != NULL, 0);
1276 g_return_val_if_fail (color != NULL, 0);
1278 colors = cmap->colors;
1282 for (i = 0; i < cmap->size; i++)
1284 if ((!available) || (available && available[i]))
1286 rdiff = (color->red - colors[i].red);
1287 gdiff = (color->green - colors[i].green);
1288 bdiff = (color->blue - colors[i].blue);
1290 sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1304 gdk_colormap_get_screen (GdkColormap *cmap)
1306 g_return_val_if_fail (cmap != NULL, NULL);
1308 return gdk_screen_get_default ();