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);
119 G_OBJECT_CLASS (parent_class)->finalize (object);
122 /* Mimics XAllocColorCells. Allocate read/write color cells. */
125 alloc_color_cells (GdkColormap *cmap,
127 unsigned long plane_masks_return[],
128 unsigned int nplanes,
129 unsigned long pixels_return[],
130 unsigned int npixels)
132 GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
133 gint i, nfree, iret, start = 0;
135 GDK_NOTE (COLORMAP, g_print ("alloc_color_cells: cmap=%p contig=%s npl=%d npix=%d",
136 cmapp, contig ? "TRUE" : "FALSE",
139 switch (cmap->visual->type)
141 case GDK_VISUAL_GRAYSCALE:
142 case GDK_VISUAL_PSEUDO_COLOR:
144 for (i = 0; i < cmap->size && nfree < npixels; i++)
145 if (cmapp->use[i] == GDK_WIN32_PE_AVAILABLE &&
147 (nfree == 0 || cmapp->use[i-1] == GDK_WIN32_PE_AVAILABLE)))
158 GDK_NOTE (COLORMAP, g_print ("...nope (%d > %d)\n", npixels, nfree));
162 GDK_NOTE (COLORMAP, g_print ("...ok\n"));
165 for (i = start; i < cmap->size && iret < npixels; i++)
166 if (cmapp->use[i] == GDK_WIN32_PE_AVAILABLE)
168 cmapp->use[i] = GDK_WIN32_PE_INUSE;
169 pixels_return[iret] = i;
172 g_assert (iret == npixels);
176 g_assert_not_reached ();
182 /* The following functions are originally from Tk8.0, but heavily
183 modified. Here are tk's licensing terms. I hope these terms don't
184 conflict with the GNU Lesser General Public License? They
185 shouldn't, as they are looser that the GLPL, yes? */
188 This software is copyrighted by the Regents of the University of
189 California, Sun Microsystems, Inc., and other parties. The following
190 terms apply to all files associated with the software unless explicitly
191 disclaimed in individual files.
193 The authors hereby grant permission to use, copy, modify, distribute,
194 and license this software and its documentation for any purpose, provided
195 that existing copyright notices are retained in all copies and that this
196 notice is included verbatim in any distributions. No written agreement,
197 license, or royalty fee is required for any of the authorized uses.
198 Modifications to this software may be copyrighted by their authors
199 and need not follow the licensing terms described here, provided that
200 the new terms are clearly indicated on the first page of each file where
203 IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
204 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
205 ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
206 DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
207 POSSIBILITY OF SUCH DAMAGE.
209 THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
210 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
211 FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
212 IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
213 NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
216 GOVERNMENT USE: If you are acquiring this software on behalf of the
217 U.S. government, the Government shall have only "Restricted Rights"
218 in the software and related documentation as defined in the Federal
219 Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
220 are acquiring the software on behalf of the Department of Defense, the
221 software shall be classified as "Commercial Computer Software" and the
222 Government shall have only "Restricted Rights" as defined in Clause
223 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
224 authors grant the U.S. Government and others acting in its behalf
225 permission to use and distribute the software in accordance with the
226 terms specified in this license.
229 /* Mimics XAllocColor. Allocate a read-only colormap entry. */
232 alloc_color (GdkColormap *cmap,
236 PALETTEENTRY entry, close_entry;
239 GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
245 new_pixel = RGB (entry.peRed, entry.peGreen, entry.peBlue);
247 switch (cmap->visual->type)
249 case GDK_VISUAL_PSEUDO_COLOR:
250 /* Find the nearest existing palette entry. */
251 index = GetNearestPaletteIndex (cmapp->hpal, new_pixel);
252 GetPaletteEntries (cmapp->hpal, index, 1, &close_entry);
255 g_print ("alloc_color: new_pixel=%06lx index=%d=%02x close=%06lx\n",
256 new_pixel, index, index,
257 RGB (close_entry.peRed, close_entry.peGreen, close_entry.peBlue)));
259 if (new_pixel != RGB (close_entry.peRed, close_entry.peGreen,
262 /* Not a perfect match. */
263 if (cmapp->use[index] == GDK_WIN32_PE_AVAILABLE)
265 /* It was a nonused entry anyway, so we can use it, and
266 * set it to the correct color.
268 GDK_NOTE (COLORMAP, g_print ("...was free\n"));
269 if (!SetPaletteEntries (cmapp->hpal, index, 1, &entry))
270 WIN32_GDI_FAILED ("SetPaletteEntries");
274 /* The close entry found is in use, so search for a
277 gboolean done = FALSE;
278 for (i = 0; i < cmap->size; i++)
279 if (cmapp->use[i] == GDK_WIN32_PE_AVAILABLE)
281 /* An available slot, use it. */
283 g_print ("...use free slot %d%s\n",
284 i, (i >= cmapp->current_size) ?
285 ", will resize palette" : ""));
286 if (i >= cmapp->current_size)
288 if (!ResizePalette (cmapp->hpal, i + 1))
290 WIN32_GDI_FAILED ("ResizePalette");
293 cmapp->current_size = i + 1;
295 if (!SetPaletteEntries (cmapp->hpal, i, 1, &entry))
297 WIN32_GDI_FAILED ("SetPaletteEntries");
309 /* No free slots available, or failed to resize
310 * palette or set palette entry.
312 GDK_NOTE (COLORMAP, g_print ("... failure\n"));
319 /* We got a match, so use it. */
323 cmapp->use[index] = GDK_WIN32_PE_INUSE;
324 GDK_NOTE (COLORMAP, g_print ("alloc_color: %p: "
325 "index=%3d=%02x for %02x %02x %02x: "
327 cmapp->hpal, index, index,
328 entry.peRed, entry.peGreen, entry.peBlue,
329 color->peRed, color->peGreen, color->peBlue));
332 case GDK_VISUAL_STATIC_COLOR:
333 /* Find the nearest existing palette entry. */
334 index = GetNearestPaletteIndex (cmapp->hpal, new_pixel);
335 GetPaletteEntries (cmapp->hpal, index, 1, &close_entry);
336 *color = close_entry;
338 GDK_NOTE (COLORMAP, g_print ("alloc_color %p: "
339 "index=%3d=%02x for %02x %02x %02x: "
341 cmapp->hpal, index, index,
342 entry.peRed, entry.peGreen, entry.peBlue,
343 color->peRed, color->peGreen, color->peBlue));
346 case GDK_VISUAL_TRUE_COLOR:
347 /* Determine what color will actually be used on non-colormap systems. */
349 *pixelp = GetNearestColor (_gdk_display_hdc, new_pixel);
350 color->peRed = GetRValue (*pixelp);
351 color->peGreen = GetGValue (*pixelp);
352 color->peBlue = GetBValue (*pixelp);
356 g_assert_not_reached ();
361 /* Mimics XFreeColors. */
364 free_colors (GdkColormap *cmap,
370 GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
372 #ifdef G_ENABLE_DEBUG
373 gint set_black_count = 0;
375 gboolean *cleared_entries;
377 cleared_entries = g_new0 (gboolean, cmap->size);
379 /* We don't have to do anything for non-palette devices. */
381 switch (cmap->visual->type)
383 case GDK_VISUAL_GRAYSCALE:
384 case GDK_VISUAL_PSEUDO_COLOR:
385 for (i = 0; i < npixels; i++)
387 if (pixels[i] >= cmap->size)
389 else if (cmapp->use[pixels[i]] == GDK_WIN32_PE_STATIC)
390 ; /* Nothing either*/
393 cmapp->use[pixels[i]] = GDK_WIN32_PE_AVAILABLE;
394 cleared_entries[pixels[i]] = TRUE;
397 for (i = cmapp->current_size - 1; i >= 0; i--)
398 if (cmapp->use[i] != GDK_WIN32_PE_AVAILABLE)
400 if (i < cmapp->current_size - 1)
402 GDK_NOTE (COLORMAP, g_print ("free_colors: hpal=%p resize=%d\n",
403 cmapp->hpal, i + 1));
404 if (!ResizePalette (cmapp->hpal, i + 1))
405 WIN32_GDI_FAILED ("ResizePalette");
407 cmapp->current_size = i + 1;
409 pe.peRed = pe.peGreen = pe.peBlue = pe.peFlags = 0;
410 for (i = 0; i < cmapp->current_size; i++)
412 if (cleared_entries[i])
414 if (!SetPaletteEntries (cmapp->hpal, i, 1, &pe))
415 WIN32_GDI_FAILED ("SetPaletteEntries");
416 GDK_NOTE (COLORMAP, set_black_count++);
420 GDK_NOTE (COLORMAP, _gdk_win32_print_hpalette (cmapp->hpal));
422 GDK_NOTE (COLORMAP, (set_black_count > 0 ?
423 g_print ("free_colors: %d (%d) set to black\n",
424 set_black_count, cmapp->current_size)
427 g_free (cleared_entries);
432 g_assert_not_reached ();
436 /* Mimics XCreateColormap. */
439 create_colormap (GdkColormap *cmap,
444 PALETTEENTRY pe[256-1];
447 GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
450 /* Allocate a starting palette with all the static colors. */
451 hpal = GetStockObject (DEFAULT_PALETTE);
452 lp.pal.palVersion = 0x300;
453 lp.pal.palNumEntries = GetPaletteEntries (hpal, 0, 256, lp.pal.palPalEntry);
455 if (cmap->visual->type == GDK_VISUAL_STATIC_COLOR &&
456 cmap->visual->depth == 4)
458 /* Use only 16 colors */
459 for (i = 8; i < 16; i++)
460 lp.pal.palPalEntry[i] = lp.pal.palPalEntry[i+4];
461 lp.pal.palNumEntries = 16;
464 for (i = 0; i < lp.pal.palNumEntries; i++)
465 lp.pal.palPalEntry[i].peFlags = 0;
466 GDK_NOTE (COLORMAP, (g_print ("Default palette %p: %d entries\n",
467 hpal, lp.pal.palNumEntries),
468 _gdk_win32_print_paletteentries (lp.pal.palPalEntry,
469 lp.pal.palNumEntries)));
472 /* For writeable colormaps, allow all 256 entries to be set. They won't
473 * set all 256 system palette entries anyhow, of course, but we shouldn't
474 * let the app see that, I think.
477 cmapp->current_size = 0;
479 cmapp->current_size = lp.pal.palNumEntries;
481 cmapp->private_val = writeable;
483 if (!(cmapp->hpal = CreatePalette (&lp.pal)))
484 WIN32_GDI_FAILED ("CreatePalette");
486 GDK_NOTE (COLORMAP, g_print ("Created palette %p\n", cmapp->hpal));
488 switch (cmap->visual->type)
490 case GDK_VISUAL_PSEUDO_COLOR:
491 cmapp->use = g_new (GdkWin32PalEntryState, cmap->size);
493 /* Mark static colors in use. */
494 for (i = 0; i < cmapp->current_size; i++)
496 cmapp->use[i] = GDK_WIN32_PE_STATIC;
497 cmapp->info[i].ref_count = G_MAXUINT/2;
499 /* Mark rest not in use */
500 for (; i < cmap->size; i++)
501 cmapp->use[i] = GDK_WIN32_PE_AVAILABLE;
510 sync_colors (GdkColormap *colormap)
513 GdkColormapPrivateWin32 *private = GDK_WIN32_COLORMAP_DATA (colormap);
517 pe = g_new (PALETTEENTRY, colormap->size);
518 nlookup = GetPaletteEntries (private->hpal, 0, colormap->size, pe);
520 GDK_NOTE (COLORMAP, (g_print ("sync_colors: %p hpal=%p: %d entries\n",
521 private, private->hpal, nlookup),
522 _gdk_win32_print_paletteentries (pe, nlookup)));
524 for (i = 0; i < nlookup; i++)
526 colormap->colors[i].pixel = i;
527 colormap->colors[i].red = (pe[i].peRed * 65535) / 255;
528 colormap->colors[i].green = (pe[i].peGreen * 65535) / 255;
529 colormap->colors[i].blue = (pe[i].peBlue * 65535) / 255;
532 for ( ; i < colormap->size; i++)
534 colormap->colors[i].pixel = i;
535 colormap->colors[i].red = 0;
536 colormap->colors[i].green = 0;
537 colormap->colors[i].blue = 0;
544 gdk_colormap_new (GdkVisual *visual,
545 gboolean private_cmap)
547 GdkColormap *colormap;
548 GdkColormapPrivateWin32 *private;
550 g_return_val_if_fail (visual != NULL, NULL);
552 colormap = g_object_new (gdk_colormap_get_type (), NULL);
553 private = GDK_WIN32_COLORMAP_DATA (colormap);
555 colormap->visual = visual;
557 colormap->size = visual->colormap_size;
559 switch (visual->type)
561 case GDK_VISUAL_GRAYSCALE:
562 case GDK_VISUAL_PSEUDO_COLOR:
563 private->info = g_new0 (GdkColorInfo, colormap->size);
564 colormap->colors = g_new (GdkColor, colormap->size);
566 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
567 (GEqualFunc) gdk_color_equal);
569 create_colormap (colormap, private_cmap);
573 sync_colors (colormap);
574 #if 0 /* XXX is this needed or not? Seems redundant */
575 gdk_colormap_change (colormap, colormap->size);
580 case GDK_VISUAL_STATIC_GRAY:
581 case GDK_VISUAL_STATIC_COLOR:
582 create_colormap (colormap, FALSE);
583 colormap->colors = g_new (GdkColor, colormap->size);
584 sync_colors (colormap);
587 case GDK_VISUAL_TRUE_COLOR:
591 g_assert_not_reached ();
598 gdk_screen_get_system_colormap (GdkScreen *screen)
600 static GdkColormap *colormap = NULL;
601 GdkColormapPrivateWin32 *private;
605 colormap = g_object_new (gdk_colormap_get_type (), NULL);
606 private = GDK_WIN32_COLORMAP_DATA (colormap);
608 colormap->visual = gdk_visual_get_system ();
610 colormap->size = colormap->visual->colormap_size;
612 private->private_val = FALSE;
614 switch (colormap->visual->type)
616 case GDK_VISUAL_GRAYSCALE:
617 case GDK_VISUAL_PSEUDO_COLOR:
618 private->info = g_new0 (GdkColorInfo, colormap->size);
619 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
620 (GEqualFunc) gdk_color_equal);
623 case GDK_VISUAL_STATIC_GRAY:
624 case GDK_VISUAL_STATIC_COLOR:
625 create_colormap (colormap, FALSE);
627 colormap->colors = g_new (GdkColor, colormap->size);
628 sync_colors (colormap);
631 case GDK_VISUAL_TRUE_COLOR:
635 g_assert_not_reached ();
643 gdk_colormap_get_system_size (void)
645 return gdk_colormap_get_system ()->size;
649 gdk_colormap_change (GdkColormap *colormap,
652 GdkColormapPrivateWin32 *cmapp;
656 g_return_if_fail (colormap != NULL);
658 cmapp = GDK_WIN32_COLORMAP_DATA (colormap);
660 GDK_NOTE (COLORMAP, g_print ("gdk_colormap_change: hpal=%p ncolors=%d\n",
661 cmapp->hpal, ncolors));
663 switch (colormap->visual->type)
665 case GDK_VISUAL_GRAYSCALE:
666 case GDK_VISUAL_PSEUDO_COLOR:
667 pe = g_new (PALETTEENTRY, ncolors);
669 for (i = 0; i < ncolors; i++)
671 pe[i].peRed = (colormap->colors[i].red >> 8);
672 pe[i].peGreen = (colormap->colors[i].green >> 8);
673 pe[i].peBlue = (colormap->colors[i].blue >> 8);
677 if (!SetPaletteEntries (cmapp->hpal, 0, ncolors, pe))
678 WIN32_GDI_FAILED ("SetPaletteEntries");
688 gdk_colors_alloc (GdkColormap *colormap,
695 GdkColormapPrivateWin32 *private;
699 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), 0);
701 private = GDK_WIN32_COLORMAP_DATA (colormap);
703 return_val = alloc_color_cells (colormap, contiguous,
704 planes, nplanes, pixels, npixels);
708 for (i = 0; i < npixels; i++)
710 private->info[pixels[i]].ref_count++;
711 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
715 return return_val != 0;
719 gdk_colors_free (GdkColormap *colormap,
724 GdkColormapPrivateWin32 *private;
729 g_return_if_fail (GDK_IS_COLORMAP (colormap));
730 g_return_if_fail (in_pixels != NULL);
732 private = GDK_WIN32_COLORMAP_DATA (colormap);
734 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
735 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
738 pixels = g_new (gulong, in_npixels);
740 for (i = 0; i < in_npixels; i++)
742 gulong pixel = in_pixels[i];
744 if (private->use[pixel] == GDK_WIN32_PE_STATIC)
747 if (private->info[pixel].ref_count)
749 private->info[pixel].ref_count--;
751 if (private->info[pixel].ref_count == 0)
753 pixels[npixels++] = pixel;
754 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
755 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
756 private->info[pixel].flags = 0;
762 free_colors (colormap, pixels, npixels, planes);
768 gdk_colormap_free_colors (GdkColormap *colormap,
775 g_return_if_fail (GDK_IS_COLORMAP (colormap));
776 g_return_if_fail (colors != NULL);
778 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
779 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
782 pixels = g_new (gulong, ncolors);
784 for (i = 0; i < ncolors; i++)
785 pixels[i] = colors[i].pixel;
787 gdk_colors_free (colormap, pixels, ncolors, 0);
792 /********************
794 ********************/
796 /* Try to allocate a single color using alloc_color. If it succeeds,
797 * cache the result in our colormap, and store in ret.
800 gdk_colormap_alloc1 (GdkColormap *colormap,
804 GdkColormapPrivateWin32 *private;
807 private = GDK_WIN32_COLORMAP_DATA (colormap);
809 pe.peRed = color->red >> 8;
810 pe.peGreen = color->green >> 8;
811 pe.peBlue = color->blue >> 8;
813 if (alloc_color (colormap, &pe, &ret->pixel))
815 ret->red = (pe.peRed * 65535) / 255;
816 ret->green = (pe.peGreen * 65535) / 255;
817 ret->blue = (pe.peBlue * 65535) / 255;
819 if ((guint) ret->pixel < colormap->size)
821 if (private->info[ret->pixel].ref_count) /* got a duplicate */
826 colormap->colors[ret->pixel] = *color;
827 colormap->colors[ret->pixel].pixel = ret->pixel;
828 private->info[ret->pixel].ref_count = 1;
830 g_hash_table_insert (private->hash,
831 &colormap->colors[ret->pixel],
832 &colormap->colors[ret->pixel]);
841 gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
848 GdkColormapPrivateWin32 *private;
853 private = GDK_WIN32_COLORMAP_DATA (colormap);
855 if (private->private_val)
858 for (i=0; i<ncolors; i++)
860 while ((index < colormap->size) &&
861 (private->info[index].ref_count != 0))
864 if (index < colormap->size)
866 colors[i].pixel = index;
868 private->info[index].ref_count++;
869 private->info[i].flags |= GDK_COLOR_WRITEABLE;
878 pixels = g_new (gulong, ncolors);
880 /* Allocation of a writeable color cells */
881 status = alloc_color_cells (colormap, FALSE, NULL, 0, pixels, ncolors);
884 for (i = 0; i < ncolors; i++)
886 colors[i].pixel = pixels[i];
887 private->info[pixels[i]].ref_count++;
888 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
894 return status ? ncolors : 0;
899 gdk_colormap_alloc_colors_private (GdkColormap *colormap,
906 GdkColormapPrivateWin32 *cmapp;
911 cmapp = GDK_WIN32_COLORMAP_DATA (colormap);
914 /* First, store the colors we have room for */
917 for (i = 0; i < ncolors; i++)
921 while ((index < colormap->size) &&
922 (cmapp->info[index].ref_count != 0))
925 if (index < colormap->size)
927 if (index >= cmapp->current_size)
929 if (!ResizePalette (cmapp->hpal, index + 1))
931 WIN32_GDI_FAILED ("ResizePalette");
935 cmapp->current_size = index + 1;
937 if (index < cmapp->current_size)
939 pe.peRed = colors[i].red >> 8;
940 pe.peBlue = colors[i].blue >> 8;
941 pe.peGreen = colors[i].green >> 8;
944 if (!SetPaletteEntries (cmapp->hpal, index, 1, &pe))
946 WIN32_GDI_FAILED ("SetPaletteEntries");
953 colors[i].pixel = index;
954 colormap->colors[index] = colors[i];
955 cmapp->info[index].ref_count++;
964 if (nremaining > 0 && best_match)
966 /* Get best matches for remaining colors */
968 gchar *available = g_new (gchar, colormap->size);
969 for (i = 0; i < colormap->size; i++)
972 for (i=0; i<ncolors; i++)
976 index = gdk_colormap_match_color (colormap,
981 colors[i] = colormap->colors[index];
982 cmapp->info[index].ref_count++;
992 return (ncolors - nremaining);
996 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
1000 gboolean best_match,
1003 GdkColormapPrivateWin32 *private;
1005 gint nremaining = 0;
1008 private = GDK_WIN32_COLORMAP_DATA (colormap);
1011 for (i = 0; i < ncolors; i++)
1015 if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
1023 if (nremaining > 0 && best_match)
1025 gchar *available = g_new (gchar, colormap->size);
1026 for (i = 0; i < colormap->size; i++)
1027 available[i] = ((private->info[i].ref_count == 0) ||
1028 !(private->info[i].flags & GDK_COLOR_WRITEABLE));
1029 while (nremaining > 0)
1031 for (i = 0; i < ncolors; i++)
1035 index = gdk_colormap_match_color (colormap, &colors[i], available);
1038 if (private->info[index].ref_count)
1040 private->info[index].ref_count++;
1041 colors[i] = colormap->colors[index];
1047 if (gdk_colormap_alloc1 (colormap,
1048 &colormap->colors[index],
1057 available[index] = FALSE;
1065 success[i] = 2; /* flag as permanent failure */
1073 /* Change back the values we flagged as permanent failures */
1076 for (i = 0; i < ncolors; i++)
1077 if (success[i] == 2)
1079 nremaining = nfailed;
1082 return (ncolors - nremaining);
1086 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
1090 gboolean best_match,
1093 GdkColormapPrivateWin32 *private;
1094 GdkColor *lookup_color;
1096 gint nremaining = 0;
1098 private = GDK_WIN32_COLORMAP_DATA (colormap);
1100 /* Check for an exact match among previously allocated colors */
1102 for (i = 0; i < ncolors; i++)
1106 lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
1109 private->info[lookup_color->pixel].ref_count++;
1110 colors[i].pixel = lookup_color->pixel;
1118 /* If that failed, we try to allocate a new color, or approxmiate
1119 * with what we can get if best_match is TRUE.
1123 if (private->private_val)
1124 return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
1126 return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
1133 gdk_colormap_alloc_colors (GdkColormap *colormap,
1137 gboolean best_match,
1140 GdkColormapPrivateWin32 *private;
1143 gint nremaining = 0;
1146 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1147 g_return_val_if_fail (colors != NULL, FALSE);
1149 private = GDK_WIN32_COLORMAP_DATA (colormap);
1151 for (i = 0; i < ncolors; i++)
1154 switch (colormap->visual->type)
1156 case GDK_VISUAL_PSEUDO_COLOR:
1157 case GDK_VISUAL_GRAYSCALE:
1159 return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
1160 writeable, best_match, success);
1162 return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
1163 writeable, best_match, success);
1166 case GDK_VISUAL_TRUE_COLOR:
1167 visual = colormap->visual;
1169 for (i = 0; i < ncolors; i++)
1172 (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
1173 ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
1174 ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
1179 case GDK_VISUAL_STATIC_GRAY:
1180 case GDK_VISUAL_STATIC_COLOR:
1181 for (i = 0; i < ncolors; i++)
1183 pe.peRed = colors[i].red >> 8;
1184 pe.peGreen = colors[i].green >> 8;
1185 pe.peBlue = colors[i].blue >> 8;
1186 if (alloc_color (colormap, &pe, &colors[i].pixel))
1193 case GDK_VISUAL_DIRECT_COLOR:
1194 g_assert_not_reached ();
1201 gdk_colormap_query_color (GdkColormap *colormap,
1207 g_return_if_fail (GDK_IS_COLORMAP (colormap));
1209 visual = gdk_colormap_get_visual (colormap);
1211 switch (visual->type)
1213 case GDK_VISUAL_DIRECT_COLOR:
1214 case GDK_VISUAL_TRUE_COLOR:
1215 result->red = 65535. * (double)((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
1216 result->green = 65535. * (double)((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
1217 result->blue = 65535. * (double)((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
1220 case GDK_VISUAL_STATIC_GRAY:
1221 case GDK_VISUAL_GRAYSCALE:
1222 result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
1225 case GDK_VISUAL_STATIC_COLOR:
1226 case GDK_VISUAL_PSEUDO_COLOR:
1227 result->red = colormap->colors[pixel].red;
1228 result->green = colormap->colors[pixel].green;
1229 result->blue = colormap->colors[pixel].blue;
1233 g_assert_not_reached ();
1239 gdk_color_change (GdkColormap *colormap,
1242 GdkColormapPrivateWin32 *private;
1245 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1246 g_return_val_if_fail (color != NULL, FALSE);
1248 private = GDK_WIN32_COLORMAP_DATA (colormap);
1250 if (color->pixel < 0 || color->pixel >= colormap->size)
1253 if (private->use[color->pixel] == GDK_WIN32_PE_STATIC)
1256 pe.peRed = color->red >> 8;
1257 pe.peGreen = color->green >> 8;
1258 pe.peBlue = color->blue >> 8;
1260 if (SetPaletteEntries (private->hpal, color->pixel, 1, &pe) == 0)
1261 WIN32_GDI_FAILED ("SetPaletteEntries");
1267 gdk_colormap_match_color (GdkColormap *cmap,
1269 const gchar *available)
1273 gint rdiff, gdiff, bdiff;
1276 g_return_val_if_fail (cmap != NULL, 0);
1277 g_return_val_if_fail (color != NULL, 0);
1279 colors = cmap->colors;
1283 for (i = 0; i < cmap->size; i++)
1285 if ((!available) || (available && available[i]))
1287 rdiff = (color->red - colors[i].red);
1288 gdiff = (color->green - colors[i].green);
1289 bdiff = (color->blue - colors[i].blue);
1291 sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1305 gdk_colormap_get_screen (GdkColormap *cmap)
1307 g_return_val_if_fail (cmap != NULL, NULL);
1309 return gdk_screen_get_default ();