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 GDI_CALL (DeleteObject, (private->hpal));
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",
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 GDI_CALL (SetPaletteEntries, (cmapp->hpal, index, 1, &entry));
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 GDI_CALL (SetPaletteEntries, (cmapp->hpal, i, 1, &pe));
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;
602 g_return_val_if_fail (screen == _gdk_screen, NULL);
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 (GDK_IS_COLORMAP (colormap));
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 GDI_CALL (SetPaletteEntries, (cmapp->hpal, 0, ncolors, pe));
688 gdk_colors_alloc (GdkColormap *colormap,
695 GdkColormapPrivateWin32 *private;
699 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
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,
769 const GdkColor *colors,
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);
1148 g_return_val_if_fail (success != NULL, ncolors);
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 GDI_CALL (SetPaletteEntries, (private->hpal, color->pixel, 1, &pe));
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 (GDK_IS_COLORMAP (cmap), NULL);