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/.
34 #include "gdkscreen.h"
35 #include "gdkinternals.h"
36 #include "gdkprivate-win32.h"
38 static gint gdk_colormap_match_color (GdkColormap *cmap,
40 const gchar *available);
41 static void gdk_colormap_init (GdkColormap *colormap);
42 static void gdk_colormap_class_init (GdkColormapClass *klass);
43 static void gdk_colormap_finalize (GObject *object);
45 static gpointer parent_class = NULL;
48 gdk_colormap_get_type (void)
50 static GType object_type = 0;
54 static const GTypeInfo object_info =
56 sizeof (GdkColormapClass),
58 (GBaseFinalizeFunc) NULL,
59 (GClassInitFunc) gdk_colormap_class_init,
60 NULL, /* class_finalize */
61 NULL, /* class_data */
64 (GInstanceInitFunc) gdk_colormap_init,
67 object_type = g_type_register_static (G_TYPE_OBJECT,
76 gdk_colormap_init (GdkColormap *colormap)
78 GdkColormapPrivateWin32 *private;
80 private = g_new (GdkColormapPrivateWin32, 1);
82 colormap->windowing_data = private;
85 private->current_size = 0;
91 colormap->colors = NULL;
95 gdk_colormap_class_init (GdkColormapClass *klass)
97 GObjectClass *object_class = G_OBJECT_CLASS (klass);
99 parent_class = g_type_class_peek_parent (klass);
101 object_class->finalize = gdk_colormap_finalize;
105 gdk_colormap_finalize (GObject *object)
107 GdkColormap *colormap = GDK_COLORMAP (object);
108 GdkColormapPrivateWin32 *private = GDK_WIN32_COLORMAP_DATA (colormap);
110 if (!DeleteObject (private->hpal))
111 WIN32_GDI_FAILED ("DeleteObject");
114 g_hash_table_destroy (private->hash);
116 g_free (private->info);
117 g_free (colormap->colors);
120 G_OBJECT_CLASS (parent_class)->finalize (object);
123 /* Mimics XAllocColorCells. Allocate read/write color cells. */
126 alloc_color_cells (GdkColormap *cmap,
128 unsigned long plane_masks_return[],
129 unsigned int nplanes,
130 unsigned long pixels_return[],
131 unsigned int npixels)
133 GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
134 gint i, nfree, iret, start = 0;
136 GDK_NOTE (COLORMAP, g_print ("alloc_color_cells: cmap=%p contig=%s npl=%d npix=%d",
137 cmapp, contig ? "TRUE" : "FALSE",
140 switch (cmap->visual->type)
142 case GDK_VISUAL_GRAYSCALE:
143 case GDK_VISUAL_PSEUDO_COLOR:
145 for (i = 0; i < cmap->size && nfree < npixels; i++)
146 if (cmapp->use[i] == GDK_WIN32_PE_AVAILABLE &&
148 (nfree == 0 || cmapp->use[i-1] == GDK_WIN32_PE_AVAILABLE)))
159 GDK_NOTE (COLORMAP, g_print ("...nope (%d > %d)\n", npixels, nfree));
163 GDK_NOTE (COLORMAP, g_print ("...ok\n"));
166 for (i = start; i < cmap->size && iret < npixels; i++)
167 if (cmapp->use[i] == GDK_WIN32_PE_AVAILABLE)
169 cmapp->use[i] = GDK_WIN32_PE_INUSE;
170 pixels_return[iret] = i;
173 g_assert (iret == npixels);
177 g_assert_not_reached ();
183 /* The following functions are originally from Tk8.0, but heavily
184 modified. Here are tk's licensing terms. I hope these terms don't
185 conflict with the GNU Lesser General Public License? They
186 shouldn't, as they are looser that the GLPL, yes? */
189 This software is copyrighted by the Regents of the University of
190 California, Sun Microsystems, Inc., and other parties. The following
191 terms apply to all files associated with the software unless explicitly
192 disclaimed in individual files.
194 The authors hereby grant permission to use, copy, modify, distribute,
195 and license this software and its documentation for any purpose, provided
196 that existing copyright notices are retained in all copies and that this
197 notice is included verbatim in any distributions. No written agreement,
198 license, or royalty fee is required for any of the authorized uses.
199 Modifications to this software may be copyrighted by their authors
200 and need not follow the licensing terms described here, provided that
201 the new terms are clearly indicated on the first page of each file where
204 IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
205 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
206 ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
207 DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
208 POSSIBILITY OF SUCH DAMAGE.
210 THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
211 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
212 FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
213 IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
214 NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
217 GOVERNMENT USE: If you are acquiring this software on behalf of the
218 U.S. government, the Government shall have only "Restricted Rights"
219 in the software and related documentation as defined in the Federal
220 Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
221 are acquiring the software on behalf of the Department of Defense, the
222 software shall be classified as "Commercial Computer Software" and the
223 Government shall have only "Restricted Rights" as defined in Clause
224 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
225 authors grant the U.S. Government and others acting in its behalf
226 permission to use and distribute the software in accordance with the
227 terms specified in this license.
230 /* Mimics XAllocColor. Allocate a read-only colormap entry. */
233 alloc_color (GdkColormap *cmap,
237 PALETTEENTRY entry, close_entry;
240 GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
246 new_pixel = RGB (entry.peRed, entry.peGreen, entry.peBlue);
248 switch (cmap->visual->type)
250 case GDK_VISUAL_PSEUDO_COLOR:
251 /* Find the nearest existing palette entry. */
252 index = GetNearestPaletteIndex (cmapp->hpal, new_pixel);
253 GetPaletteEntries (cmapp->hpal, index, 1, &close_entry);
256 g_print ("alloc_color: new_pixel=%06lx index=%d=%02x close=%06lx\n",
257 new_pixel, index, index,
258 RGB (close_entry.peRed, close_entry.peGreen, close_entry.peBlue)));
260 if (new_pixel != RGB (close_entry.peRed, close_entry.peGreen,
263 /* Not a perfect match. */
264 if (cmapp->use[index] == GDK_WIN32_PE_AVAILABLE)
266 /* It was a nonused entry anyway, so we can use it, and
267 * set it to the correct color.
269 GDK_NOTE (COLORMAP, g_print ("...was free\n"));
270 if (!SetPaletteEntries (cmapp->hpal, index, 1, &entry))
271 WIN32_GDI_FAILED ("SetPaletteEntries");
275 /* The close entry found is in use, so search for a
278 gboolean done = FALSE;
279 for (i = 0; i < cmap->size; i++)
280 if (cmapp->use[i] == GDK_WIN32_PE_AVAILABLE)
282 /* An available slot, use it. */
284 g_print ("...use free slot %d%s\n",
285 i, (i >= cmapp->current_size) ?
286 ", will resize palette" : ""));
287 if (i >= cmapp->current_size)
289 if (!ResizePalette (cmapp->hpal, i + 1))
291 WIN32_GDI_FAILED ("ResizePalette");
294 cmapp->current_size = i + 1;
296 if (!SetPaletteEntries (cmapp->hpal, i, 1, &entry))
298 WIN32_GDI_FAILED ("SetPaletteEntries");
310 /* No free slots available, or failed to resize
311 * palette or set palette entry.
313 GDK_NOTE (COLORMAP, g_print ("... failure\n"));
320 /* We got a match, so use it. */
324 cmapp->use[index] = GDK_WIN32_PE_INUSE;
325 GDK_NOTE (COLORMAP, g_print ("alloc_color: %p: "
326 "index=%3d=%02x for %02x %02x %02x: "
328 cmapp->hpal, index, index,
329 entry.peRed, entry.peGreen, entry.peBlue,
330 color->peRed, color->peGreen, color->peBlue));
333 case GDK_VISUAL_STATIC_COLOR:
334 /* Find the nearest existing palette entry. */
335 index = GetNearestPaletteIndex (cmapp->hpal, new_pixel);
336 GetPaletteEntries (cmapp->hpal, index, 1, &close_entry);
337 *color = close_entry;
339 GDK_NOTE (COLORMAP, g_print ("alloc_color %p: "
340 "index=%3d=%02x for %02x %02x %02x: "
342 cmapp->hpal, index, index,
343 entry.peRed, entry.peGreen, entry.peBlue,
344 color->peRed, color->peGreen, color->peBlue));
347 case GDK_VISUAL_TRUE_COLOR:
348 /* Determine what color will actually be used on non-colormap systems. */
350 *pixelp = GetNearestColor (_gdk_display_hdc, new_pixel);
351 color->peRed = GetRValue (*pixelp);
352 color->peGreen = GetGValue (*pixelp);
353 color->peBlue = GetBValue (*pixelp);
357 g_assert_not_reached ();
362 /* Mimics XFreeColors. */
365 free_colors (GdkColormap *cmap,
371 GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
373 #ifdef G_ENABLE_DEBUG
374 gint set_black_count = 0;
376 gboolean *cleared_entries;
378 cleared_entries = g_new0 (gboolean, cmap->size);
380 /* We don't have to do anything for non-palette devices. */
382 switch (cmap->visual->type)
384 case GDK_VISUAL_GRAYSCALE:
385 case GDK_VISUAL_PSEUDO_COLOR:
386 for (i = 0; i < npixels; i++)
388 if (pixels[i] >= cmap->size)
390 else if (cmapp->use[pixels[i]] == GDK_WIN32_PE_STATIC)
391 ; /* Nothing either*/
394 cmapp->use[pixels[i]] = GDK_WIN32_PE_AVAILABLE;
395 cleared_entries[pixels[i]] = TRUE;
398 for (i = cmapp->current_size - 1; i >= 0; i--)
399 if (cmapp->use[i] != GDK_WIN32_PE_AVAILABLE)
401 if (i < cmapp->current_size - 1)
403 GDK_NOTE (COLORMAP, g_print ("free_colors: hpal=%p resize=%d\n",
404 cmapp->hpal, i + 1));
405 if (!ResizePalette (cmapp->hpal, i + 1))
406 WIN32_GDI_FAILED ("ResizePalette");
408 cmapp->current_size = i + 1;
410 pe.peRed = pe.peGreen = pe.peBlue = pe.peFlags = 0;
411 for (i = 0; i < cmapp->current_size; i++)
413 if (cleared_entries[i])
415 if (!SetPaletteEntries (cmapp->hpal, i, 1, &pe))
416 WIN32_GDI_FAILED ("SetPaletteEntries");
417 GDK_NOTE (COLORMAP, set_black_count++);
421 GDK_NOTE (COLORMAP, _gdk_win32_print_hpalette (cmapp->hpal));
423 GDK_NOTE (COLORMAP, (set_black_count > 0 ?
424 g_print ("free_colors: %d (%d) set to black\n",
425 set_black_count, cmapp->current_size)
428 g_free (cleared_entries);
433 g_assert_not_reached ();
437 /* Mimics XCreateColormap. */
440 create_colormap (GdkColormap *cmap,
445 PALETTEENTRY pe[256-1];
448 GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
451 /* Allocate a starting palette with all the static colors. */
452 hpal = GetStockObject (DEFAULT_PALETTE);
453 lp.pal.palVersion = 0x300;
454 lp.pal.palNumEntries = GetPaletteEntries (hpal, 0, 256, lp.pal.palPalEntry);
456 if (cmap->visual->type == GDK_VISUAL_STATIC_COLOR &&
457 cmap->visual->depth == 4)
459 /* Use only 16 colors */
460 for (i = 8; i < 16; i++)
461 lp.pal.palPalEntry[i] = lp.pal.palPalEntry[i+4];
462 lp.pal.palNumEntries = 16;
465 for (i = 0; i < lp.pal.palNumEntries; i++)
466 lp.pal.palPalEntry[i].peFlags = 0;
467 GDK_NOTE (COLORMAP, (g_print ("Default palette %p: %d entries\n",
468 hpal, lp.pal.palNumEntries),
469 _gdk_win32_print_paletteentries (lp.pal.palPalEntry,
470 lp.pal.palNumEntries)));
473 /* For writeable colormaps, allow all 256 entries to be set. They won't
474 * set all 256 system palette entries anyhow, of course, but we shouldn't
475 * let the app see that, I think.
478 cmapp->current_size = 0;
480 cmapp->current_size = lp.pal.palNumEntries;
482 cmapp->private_val = writeable;
484 if (!(cmapp->hpal = CreatePalette (&lp.pal)))
485 WIN32_GDI_FAILED ("CreatePalette");
487 GDK_NOTE (COLORMAP, g_print ("Created palette %p\n", cmapp->hpal));
489 switch (cmap->visual->type)
491 case GDK_VISUAL_PSEUDO_COLOR:
492 cmapp->use = g_new (GdkWin32PalEntryState, cmap->size);
494 /* Mark static colors in use. */
495 for (i = 0; i < cmapp->current_size; i++)
497 cmapp->use[i] = GDK_WIN32_PE_STATIC;
498 cmapp->info[i].ref_count = G_MAXUINT/2;
500 /* Mark rest not in use */
501 for (; i < cmap->size; i++)
502 cmapp->use[i] = GDK_WIN32_PE_AVAILABLE;
511 sync_colors (GdkColormap *colormap)
514 GdkColormapPrivateWin32 *private = GDK_WIN32_COLORMAP_DATA (colormap);
518 pe = g_new (PALETTEENTRY, colormap->size);
519 nlookup = GetPaletteEntries (private->hpal, 0, colormap->size, pe);
521 GDK_NOTE (COLORMAP, (g_print ("sync_colors: %p hpal=%p: %d entries\n",
522 private, private->hpal, nlookup),
523 _gdk_win32_print_paletteentries (pe, nlookup)));
525 for (i = 0; i < nlookup; i++)
527 colormap->colors[i].pixel = i;
528 colormap->colors[i].red = (pe[i].peRed * 65535) / 255;
529 colormap->colors[i].green = (pe[i].peGreen * 65535) / 255;
530 colormap->colors[i].blue = (pe[i].peBlue * 65535) / 255;
533 for ( ; i < colormap->size; i++)
535 colormap->colors[i].pixel = i;
536 colormap->colors[i].red = 0;
537 colormap->colors[i].green = 0;
538 colormap->colors[i].blue = 0;
545 gdk_colormap_new (GdkVisual *visual,
546 gboolean private_cmap)
548 GdkColormap *colormap;
549 GdkColormapPrivateWin32 *private;
551 g_return_val_if_fail (visual != NULL, NULL);
553 colormap = g_object_new (gdk_colormap_get_type (), NULL);
554 private = GDK_WIN32_COLORMAP_DATA (colormap);
556 colormap->visual = visual;
558 colormap->size = visual->colormap_size;
560 switch (visual->type)
562 case GDK_VISUAL_GRAYSCALE:
563 case GDK_VISUAL_PSEUDO_COLOR:
564 private->info = g_new0 (GdkColorInfo, colormap->size);
565 colormap->colors = g_new (GdkColor, colormap->size);
567 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
568 (GEqualFunc) gdk_color_equal);
570 create_colormap (colormap, private_cmap);
574 sync_colors (colormap);
575 #if 0 /* XXX is this needed or not? Seems redundant */
576 gdk_colormap_change (colormap, colormap->size);
581 case GDK_VISUAL_STATIC_GRAY:
582 case GDK_VISUAL_STATIC_COLOR:
583 create_colormap (colormap, FALSE);
584 colormap->colors = g_new (GdkColor, colormap->size);
585 sync_colors (colormap);
588 case GDK_VISUAL_TRUE_COLOR:
592 g_assert_not_reached ();
599 gdk_screen_get_system_colormap (GdkScreen *screen)
601 static GdkColormap *colormap = NULL;
602 GdkColormapPrivateWin32 *private;
606 colormap = g_object_new (gdk_colormap_get_type (), NULL);
607 private = GDK_WIN32_COLORMAP_DATA (colormap);
609 colormap->visual = gdk_visual_get_system ();
611 colormap->size = colormap->visual->colormap_size;
613 private->private_val = FALSE;
615 switch (colormap->visual->type)
617 case GDK_VISUAL_GRAYSCALE:
618 case GDK_VISUAL_PSEUDO_COLOR:
619 private->info = g_new0 (GdkColorInfo, colormap->size);
620 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
621 (GEqualFunc) gdk_color_equal);
624 case GDK_VISUAL_STATIC_GRAY:
625 case GDK_VISUAL_STATIC_COLOR:
626 create_colormap (colormap, FALSE);
628 colormap->colors = g_new (GdkColor, colormap->size);
629 sync_colors (colormap);
632 case GDK_VISUAL_TRUE_COLOR:
636 g_assert_not_reached ();
644 gdk_colormap_get_system_size (void)
646 return gdk_colormap_get_system ()->size;
650 gdk_colormap_change (GdkColormap *colormap,
653 GdkColormapPrivateWin32 *cmapp;
657 g_return_if_fail (colormap != NULL);
659 cmapp = GDK_WIN32_COLORMAP_DATA (colormap);
661 GDK_NOTE (COLORMAP, g_print ("gdk_colormap_change: hpal=%p ncolors=%d\n",
662 cmapp->hpal, ncolors));
664 switch (colormap->visual->type)
666 case GDK_VISUAL_GRAYSCALE:
667 case GDK_VISUAL_PSEUDO_COLOR:
668 pe = g_new (PALETTEENTRY, ncolors);
670 for (i = 0; i < ncolors; i++)
672 pe[i].peRed = (colormap->colors[i].red >> 8);
673 pe[i].peGreen = (colormap->colors[i].green >> 8);
674 pe[i].peBlue = (colormap->colors[i].blue >> 8);
678 if (!SetPaletteEntries (cmapp->hpal, 0, ncolors, pe))
679 WIN32_GDI_FAILED ("SetPaletteEntries");
689 gdk_colors_alloc (GdkColormap *colormap,
696 GdkColormapPrivateWin32 *private;
700 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), 0);
702 private = GDK_WIN32_COLORMAP_DATA (colormap);
704 return_val = alloc_color_cells (colormap, contiguous,
705 planes, nplanes, pixels, npixels);
709 for (i = 0; i < npixels; i++)
711 private->info[pixels[i]].ref_count++;
712 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
716 return return_val != 0;
720 gdk_colors_free (GdkColormap *colormap,
725 GdkColormapPrivateWin32 *private;
730 g_return_if_fail (GDK_IS_COLORMAP (colormap));
731 g_return_if_fail (in_pixels != NULL);
733 private = GDK_WIN32_COLORMAP_DATA (colormap);
735 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
736 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
739 pixels = g_new (gulong, in_npixels);
741 for (i = 0; i < in_npixels; i++)
743 gulong pixel = in_pixels[i];
745 if (private->use[pixel] == GDK_WIN32_PE_STATIC)
748 if (private->info[pixel].ref_count)
750 private->info[pixel].ref_count--;
752 if (private->info[pixel].ref_count == 0)
754 pixels[npixels++] = pixel;
755 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
756 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
757 private->info[pixel].flags = 0;
763 free_colors (colormap, pixels, npixels, planes);
769 gdk_colormap_free_colors (GdkColormap *colormap,
776 g_return_if_fail (GDK_IS_COLORMAP (colormap));
777 g_return_if_fail (colors != NULL);
779 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
780 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
783 pixels = g_new (gulong, ncolors);
785 for (i = 0; i < ncolors; i++)
786 pixels[i] = colors[i].pixel;
788 gdk_colors_free (colormap, pixels, ncolors, 0);
793 /********************
795 ********************/
797 /* Try to allocate a single color using alloc_color. If it succeeds,
798 * cache the result in our colormap, and store in ret.
801 gdk_colormap_alloc1 (GdkColormap *colormap,
805 GdkColormapPrivateWin32 *private;
808 private = GDK_WIN32_COLORMAP_DATA (colormap);
810 pe.peRed = color->red >> 8;
811 pe.peGreen = color->green >> 8;
812 pe.peBlue = color->blue >> 8;
814 if (alloc_color (colormap, &pe, &ret->pixel))
816 ret->red = (pe.peRed * 65535) / 255;
817 ret->green = (pe.peGreen * 65535) / 255;
818 ret->blue = (pe.peBlue * 65535) / 255;
820 if ((guint) ret->pixel < colormap->size)
822 if (private->info[ret->pixel].ref_count) /* got a duplicate */
827 colormap->colors[ret->pixel] = *color;
828 colormap->colors[ret->pixel].pixel = ret->pixel;
829 private->info[ret->pixel].ref_count = 1;
831 g_hash_table_insert (private->hash,
832 &colormap->colors[ret->pixel],
833 &colormap->colors[ret->pixel]);
842 gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
849 GdkColormapPrivateWin32 *private;
854 private = GDK_WIN32_COLORMAP_DATA (colormap);
856 if (private->private_val)
859 for (i=0; i<ncolors; i++)
861 while ((index < colormap->size) &&
862 (private->info[index].ref_count != 0))
865 if (index < colormap->size)
867 colors[i].pixel = index;
869 private->info[index].ref_count++;
870 private->info[i].flags |= GDK_COLOR_WRITEABLE;
879 pixels = g_new (gulong, ncolors);
881 /* Allocation of a writeable color cells */
882 status = alloc_color_cells (colormap, FALSE, NULL, 0, pixels, ncolors);
885 for (i = 0; i < ncolors; i++)
887 colors[i].pixel = pixels[i];
888 private->info[pixels[i]].ref_count++;
889 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
895 return status ? ncolors : 0;
900 gdk_colormap_alloc_colors_private (GdkColormap *colormap,
907 GdkColormapPrivateWin32 *cmapp;
912 cmapp = GDK_WIN32_COLORMAP_DATA (colormap);
915 /* First, store the colors we have room for */
918 for (i = 0; i < ncolors; i++)
922 while ((index < colormap->size) &&
923 (cmapp->info[index].ref_count != 0))
926 if (index < colormap->size)
928 if (index >= cmapp->current_size)
930 if (!ResizePalette (cmapp->hpal, index + 1))
932 WIN32_GDI_FAILED ("ResizePalette");
936 cmapp->current_size = index + 1;
938 if (index < cmapp->current_size)
940 pe.peRed = colors[i].red >> 8;
941 pe.peBlue = colors[i].blue >> 8;
942 pe.peGreen = colors[i].green >> 8;
945 if (!SetPaletteEntries (cmapp->hpal, index, 1, &pe))
947 WIN32_GDI_FAILED ("SetPaletteEntries");
954 colors[i].pixel = index;
955 colormap->colors[index] = colors[i];
956 cmapp->info[index].ref_count++;
965 if (nremaining > 0 && best_match)
967 /* Get best matches for remaining colors */
969 gchar *available = g_new (gchar, colormap->size);
970 for (i = 0; i < colormap->size; i++)
973 for (i=0; i<ncolors; i++)
977 index = gdk_colormap_match_color (colormap,
982 colors[i] = colormap->colors[index];
983 cmapp->info[index].ref_count++;
993 return (ncolors - nremaining);
997 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
1001 gboolean best_match,
1004 GdkColormapPrivateWin32 *private;
1006 gint nremaining = 0;
1009 private = GDK_WIN32_COLORMAP_DATA (colormap);
1012 for (i = 0; i < ncolors; i++)
1016 if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
1024 if (nremaining > 0 && best_match)
1026 gchar *available = g_new (gchar, colormap->size);
1027 for (i = 0; i < colormap->size; i++)
1028 available[i] = ((private->info[i].ref_count == 0) ||
1029 !(private->info[i].flags & GDK_COLOR_WRITEABLE));
1030 while (nremaining > 0)
1032 for (i = 0; i < ncolors; i++)
1036 index = gdk_colormap_match_color (colormap, &colors[i], available);
1039 if (private->info[index].ref_count)
1041 private->info[index].ref_count++;
1042 colors[i] = colormap->colors[index];
1048 if (gdk_colormap_alloc1 (colormap,
1049 &colormap->colors[index],
1058 available[index] = FALSE;
1066 success[i] = 2; /* flag as permanent failure */
1074 /* Change back the values we flagged as permanent failures */
1077 for (i = 0; i < ncolors; i++)
1078 if (success[i] == 2)
1080 nremaining = nfailed;
1083 return (ncolors - nremaining);
1087 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
1091 gboolean best_match,
1094 GdkColormapPrivateWin32 *private;
1095 GdkColor *lookup_color;
1097 gint nremaining = 0;
1099 private = GDK_WIN32_COLORMAP_DATA (colormap);
1101 /* Check for an exact match among previously allocated colors */
1103 for (i = 0; i < ncolors; i++)
1107 lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
1110 private->info[lookup_color->pixel].ref_count++;
1111 colors[i].pixel = lookup_color->pixel;
1119 /* If that failed, we try to allocate a new color, or approxmiate
1120 * with what we can get if best_match is TRUE.
1124 if (private->private_val)
1125 return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
1127 return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
1134 gdk_colormap_alloc_colors (GdkColormap *colormap,
1138 gboolean best_match,
1141 GdkColormapPrivateWin32 *private;
1144 gint nremaining = 0;
1147 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1148 g_return_val_if_fail (colors != NULL, FALSE);
1150 private = GDK_WIN32_COLORMAP_DATA (colormap);
1152 for (i = 0; i < ncolors; i++)
1155 switch (colormap->visual->type)
1157 case GDK_VISUAL_PSEUDO_COLOR:
1158 case GDK_VISUAL_GRAYSCALE:
1160 return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
1161 writeable, best_match, success);
1163 return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
1164 writeable, best_match, success);
1167 case GDK_VISUAL_TRUE_COLOR:
1168 visual = colormap->visual;
1170 for (i = 0; i < ncolors; i++)
1173 (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
1174 ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
1175 ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
1180 case GDK_VISUAL_STATIC_GRAY:
1181 case GDK_VISUAL_STATIC_COLOR:
1182 for (i = 0; i < ncolors; i++)
1184 pe.peRed = colors[i].red >> 8;
1185 pe.peGreen = colors[i].green >> 8;
1186 pe.peBlue = colors[i].blue >> 8;
1187 if (alloc_color (colormap, &pe, &colors[i].pixel))
1194 case GDK_VISUAL_DIRECT_COLOR:
1195 g_assert_not_reached ();
1202 gdk_colormap_query_color (GdkColormap *colormap,
1208 g_return_if_fail (GDK_IS_COLORMAP (colormap));
1210 visual = gdk_colormap_get_visual (colormap);
1212 switch (visual->type)
1214 case GDK_VISUAL_DIRECT_COLOR:
1215 case GDK_VISUAL_TRUE_COLOR:
1216 result->red = 65535. * (double)((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
1217 result->green = 65535. * (double)((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
1218 result->blue = 65535. * (double)((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
1221 case GDK_VISUAL_STATIC_GRAY:
1222 case GDK_VISUAL_GRAYSCALE:
1223 result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
1226 case GDK_VISUAL_STATIC_COLOR:
1227 case GDK_VISUAL_PSEUDO_COLOR:
1228 result->red = colormap->colors[pixel].red;
1229 result->green = colormap->colors[pixel].green;
1230 result->blue = colormap->colors[pixel].blue;
1234 g_assert_not_reached ();
1240 gdk_color_change (GdkColormap *colormap,
1243 GdkColormapPrivateWin32 *private;
1246 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1247 g_return_val_if_fail (color != NULL, FALSE);
1249 private = GDK_WIN32_COLORMAP_DATA (colormap);
1251 if (color->pixel < 0 || color->pixel >= colormap->size)
1254 if (private->use[color->pixel] == GDK_WIN32_PE_STATIC)
1257 pe.peRed = color->red >> 8;
1258 pe.peGreen = color->green >> 8;
1259 pe.peBlue = color->blue >> 8;
1261 if (SetPaletteEntries (private->hpal, color->pixel, 1, &pe) == 0)
1262 WIN32_GDI_FAILED ("SetPaletteEntries");
1268 gdk_colormap_match_color (GdkColormap *cmap,
1270 const gchar *available)
1274 gint rdiff, gdiff, bdiff;
1277 g_return_val_if_fail (cmap != NULL, 0);
1278 g_return_val_if_fail (color != NULL, 0);
1280 colors = cmap->colors;
1284 for (i = 0; i < cmap->size; i++)
1286 if ((!available) || (available && available[i]))
1288 rdiff = (color->red - colors[i].red);
1289 gdiff = (color->green - colors[i].green);
1290 bdiff = (color->blue - colors[i].blue);
1292 sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1306 gdk_colormap_get_screen (GdkColormap *cmap)
1308 g_return_val_if_fail (cmap != NULL, NULL);
1310 return gdk_screen_get_default ();