]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkvisual-win32.c
70f513c4e0519e2b90f2cd6cad692659bd158331
[~andy/gtk] / gdk / win32 / gdkvisual-win32.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "config.h"
28
29 #include <gdk/gdk.h>
30 #include "gdkx.h"
31
32 static void  gdk_visual_add            (GdkVisual *visual);
33 static void  gdk_visual_decompose_mask (gulong     mask,
34                                         gint      *shift,
35                                         gint      *prec);
36 static guint gdk_visual_hash           (Visual    *key);
37 static gint  gdk_visual_compare        (Visual    *a,
38                                         Visual    *b);
39
40
41 static GdkVisualPrivate *system_visual;
42 static GdkVisualPrivate *visuals;
43 static gint nvisuals;
44
45 static gint available_depths[7];
46 static gint navailable_depths;
47
48 static GdkVisualType available_types[6];
49 static gint navailable_types;
50
51 #ifdef G_ENABLE_DEBUG
52
53 static const gchar* visual_names[] =
54 {
55   "static gray",
56   "grayscale",
57   "static color",
58   "pseudo color",
59   "true color",
60   "direct color",
61 };
62
63 #endif /* G_ENABLE_DEBUG */
64
65 static GHashTable *visual_hash = NULL;
66
67 void
68 gdk_visual_init (void)
69 {
70   struct
71   {
72     BITMAPINFOHEADER bi;
73     union
74     {
75       RGBQUAD colors[256];
76       DWORD fields[256];
77     } u;
78   } bmi;
79   HBITMAP hbm;
80
81   static const gint possible_depths[7] = { 32, 24, 16, 15, 8, 4, 1 };
82   static const GdkVisualType possible_types[6] =
83     {
84       GDK_VISUAL_DIRECT_COLOR,
85       GDK_VISUAL_TRUE_COLOR,
86       GDK_VISUAL_PSEUDO_COLOR,
87       GDK_VISUAL_STATIC_COLOR,
88       GDK_VISUAL_GRAYSCALE,
89       GDK_VISUAL_STATIC_GRAY
90     };
91
92   static const gint npossible_depths = sizeof(possible_depths)/sizeof(gint);
93   static const gint npossible_types = sizeof(possible_types)/sizeof(GdkVisualType);
94
95   int rastercaps, numcolors, sizepalette, colorres, bitspixel;
96   Visual *default_xvisual;
97   GdkVisualPrivate temp_visual;
98   int nxvisuals;
99   int i, j;
100
101   nxvisuals = 1;
102   visuals = g_new (GdkVisualPrivate, nxvisuals);
103
104   nvisuals = 0;
105   for (i = 0; i < nxvisuals; i++)
106     {
107       if (1)
108         {
109           bitspixel = GetDeviceCaps (gdk_DC, BITSPIXEL);
110           rastercaps = GetDeviceCaps (gdk_DC, RASTERCAPS);
111           default_xvisual = g_new (Visual, 1);
112           visuals[nvisuals].xvisual = default_xvisual;
113           visuals[nvisuals].xvisual->visualid = nvisuals;
114           visuals[nvisuals].xvisual->bitspixel = bitspixel;
115
116           if (rastercaps & RC_PALETTE)
117             {
118               visuals[nvisuals].visual.type = GDK_VISUAL_PSEUDO_COLOR;
119               numcolors = GetDeviceCaps (gdk_DC, NUMCOLORS);
120               sizepalette = GetDeviceCaps (gdk_DC, SIZEPALETTE);
121               colorres = GetDeviceCaps (gdk_DC, COLORRES);
122               visuals[nvisuals].xvisual->map_entries = sizepalette;
123             }
124           else if (bitspixel == 1)
125             {
126               visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_GRAY;
127               visuals[nvisuals].xvisual->map_entries = 2;
128             }
129           else if (bitspixel == 4)
130             {
131               visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_COLOR;
132               visuals[nvisuals].xvisual->map_entries = 16;
133             }
134           else if (bitspixel == 8)
135             {
136               visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_COLOR;
137               visuals[nvisuals].xvisual->map_entries = 256;
138             }
139           else if (bitspixel == 16)
140             {
141               visuals[nvisuals].visual.type = GDK_VISUAL_TRUE_COLOR;
142 #if 1
143               /* This code by Mike Enright,
144                * see http://www.users.cts.com/sd/m/menright/display.html
145                */
146               memset (&bmi, 0, sizeof (bmi));
147               bmi.bi.biSize = sizeof (bmi.bi);
148   
149               hbm = CreateCompatibleBitmap (gdk_DC, 1, 1);
150               GetDIBits (gdk_DC, hbm, 0, 1, NULL,
151                          (BITMAPINFO *) &bmi, DIB_RGB_COLORS);
152               GetDIBits (gdk_DC, hbm, 0, 1, NULL,
153                          (BITMAPINFO *) &bmi, DIB_RGB_COLORS);
154               DeleteObject (hbm);
155
156               if (bmi.bi.biCompression != BI_BITFIELDS)
157                 {
158                   /* Either BI_RGB or BI_RLE_something
159                    * .... or perhaps (!!) something else.
160                    * Theoretically biCompression might be
161                    * mmioFourCC('c','v','i','d') but I doubt it.
162                    */
163                   if (bmi.bi.biCompression == BI_RGB)
164                     {
165                       /* It's 555 */
166                       bitspixel = 15;
167                       visuals[nvisuals].visual.red_mask   = 0x00007C00;
168                       visuals[nvisuals].visual.green_mask = 0x000003E0;
169                       visuals[nvisuals].visual.blue_mask  = 0x0000001F;
170                     }
171                   else
172                     {
173                       g_assert_not_reached ();
174                     }
175                 }
176               else
177                 {
178                   DWORD allmasks =
179                     bmi.u.fields[0] | bmi.u.fields[1] | bmi.u.fields[2];
180                   int k = 0;
181                   while (allmasks)
182                     {
183                       if (allmasks&1)
184                         k++;
185                       allmasks/=2;
186                     }
187                   bitspixel = k;
188                   visuals[nvisuals].visual.red_mask = bmi.u.fields[0];
189                   visuals[nvisuals].visual.green_mask = bmi.u.fields[1];
190                   visuals[nvisuals].visual.blue_mask  = bmi.u.fields[2];
191                 }
192 #else
193               /* Old, incorrect (but still working) code. */
194 #if 0
195               visuals[nvisuals].visual.red_mask   = 0x0000F800;
196               visuals[nvisuals].visual.green_mask = 0x000007E0;
197               visuals[nvisuals].visual.blue_mask  = 0x0000001F;
198 #else
199               visuals[nvisuals].visual.red_mask   = 0x00007C00;
200               visuals[nvisuals].visual.green_mask = 0x000003E0;
201               visuals[nvisuals].visual.blue_mask  = 0x0000001F;
202 #endif
203 #endif
204             }
205           else if (bitspixel == 24 || bitspixel == 32)
206             {
207               visuals[nvisuals].visual.type = GDK_VISUAL_TRUE_COLOR;
208               visuals[nvisuals].visual.red_mask   = 0x00FF0000;
209               visuals[nvisuals].visual.green_mask = 0x0000FF00;
210               visuals[nvisuals].visual.blue_mask  = 0x000000FF;
211             }
212           else
213             g_error ("gdk_visual_init: unsupported BITSPIXEL: %d\n", bitspixel);
214
215           visuals[nvisuals].visual.depth = bitspixel;
216           visuals[nvisuals].visual.byte_order = GDK_LSB_FIRST;
217           visuals[nvisuals].visual.bits_per_rgb = 42; /* Not used? */
218
219           if ((visuals[nvisuals].visual.type == GDK_VISUAL_TRUE_COLOR) ||
220               (visuals[nvisuals].visual.type == GDK_VISUAL_DIRECT_COLOR))
221             {
222               gdk_visual_decompose_mask (visuals[nvisuals].visual.red_mask,
223                                          &visuals[nvisuals].visual.red_shift,
224                                          &visuals[nvisuals].visual.red_prec);
225
226               gdk_visual_decompose_mask (visuals[nvisuals].visual.green_mask,
227                                          &visuals[nvisuals].visual.green_shift,
228                                          &visuals[nvisuals].visual.green_prec);
229
230               gdk_visual_decompose_mask (visuals[nvisuals].visual.blue_mask,
231                                          &visuals[nvisuals].visual.blue_shift,
232                                          &visuals[nvisuals].visual.blue_prec);
233               visuals[nvisuals].xvisual->map_entries =
234                 1 << (MAX (visuals[nvisuals].visual.red_prec,
235                            MAX (visuals[nvisuals].visual.green_prec,
236                                 visuals[nvisuals].visual.blue_prec)));
237             }
238           else
239             {
240               visuals[nvisuals].visual.red_mask = 0;
241               visuals[nvisuals].visual.red_shift = 0;
242               visuals[nvisuals].visual.red_prec = 0;
243
244               visuals[nvisuals].visual.green_mask = 0;
245               visuals[nvisuals].visual.green_shift = 0;
246               visuals[nvisuals].visual.green_prec = 0;
247
248               visuals[nvisuals].visual.blue_mask = 0;
249               visuals[nvisuals].visual.blue_shift = 0;
250               visuals[nvisuals].visual.blue_prec = 0;
251             }
252           visuals[nvisuals].visual.colormap_size = visuals[nvisuals].xvisual->map_entries;
253
254           nvisuals += 1;
255         }
256     }
257
258   for (i = 0; i < nvisuals; i++)
259     {
260       for (j = i+1; j < nvisuals; j++)
261         {
262           if (visuals[j].visual.depth >= visuals[i].visual.depth)
263             {
264               if ((visuals[j].visual.depth == 8) && (visuals[i].visual.depth == 8))
265                 {
266                   if (visuals[j].visual.type == GDK_VISUAL_PSEUDO_COLOR)
267                     {
268                       temp_visual = visuals[j];
269                       visuals[j] = visuals[i];
270                       visuals[i] = temp_visual;
271                     }
272                   else if ((visuals[i].visual.type != GDK_VISUAL_PSEUDO_COLOR) &&
273                            visuals[j].visual.type > visuals[i].visual.type)
274                     {
275                       temp_visual = visuals[j];
276                       visuals[j] = visuals[i];
277                       visuals[i] = temp_visual;
278                     }
279                 }
280               else if ((visuals[j].visual.depth > visuals[i].visual.depth) ||
281                        ((visuals[j].visual.depth == visuals[i].visual.depth) &&
282                         (visuals[j].visual.type > visuals[i].visual.type)))
283                 {
284                   temp_visual = visuals[j];
285                   visuals[j] = visuals[i];
286                   visuals[i] = temp_visual;
287                 }
288             }
289         }
290     }
291
292   for (i = 0; i < nvisuals; i++)
293     if (default_xvisual->visualid == visuals[i].xvisual->visualid)
294       {
295         system_visual = &visuals[i];
296         break;
297       }
298
299   navailable_depths = 0;
300   for (i = 0; i < npossible_depths; i++)
301     {
302       for (j = 0; j < nvisuals; j++)
303         {
304           if (visuals[j].visual.depth == possible_depths[i])
305             {
306               available_depths[navailable_depths++] = visuals[j].visual.depth;
307               break;
308             }
309         }
310     }
311
312   if (navailable_depths == 0)
313     g_error ("unable to find a usable depth");
314
315   navailable_types = 0;
316   for (i = 0; i < npossible_types; i++)
317     {
318       for (j = 0; j < nvisuals; j++)
319         {
320           if (visuals[j].visual.type == possible_types[i])
321             {
322               available_types[navailable_types++] = visuals[j].visual.type;
323               break;
324             }
325         }
326     }
327
328   for (i = 0; i < nvisuals; i++)
329     gdk_visual_add ((GdkVisual*) &visuals[i]);
330
331   if (npossible_types == 0)
332     g_error ("unable to find a usable visual type");
333 }
334
335 GdkVisual*
336 gdk_visual_ref (GdkVisual *visual)
337 {
338   return visual;
339 }
340
341 void
342 gdk_visual_unref (GdkVisual *visual)
343 {
344   return;
345 }
346
347 gint
348 gdk_visual_get_best_depth (void)
349 {
350   return available_depths[0];
351 }
352
353 GdkVisualType
354 gdk_visual_get_best_type (void)
355 {
356   return available_types[0];
357 }
358
359 GdkVisual*
360 gdk_visual_get_system (void)
361 {
362   return ((GdkVisual*) system_visual);
363 }
364
365 GdkVisual*
366 gdk_visual_get_best (void)
367 {
368   return ((GdkVisual*) &(visuals[0]));
369 }
370
371 GdkVisual*
372 gdk_visual_get_best_with_depth (gint depth)
373 {
374   GdkVisual *return_val;
375   int i;
376
377   return_val = NULL;
378   for (i = 0; i < nvisuals; i++)
379     if (depth == visuals[i].visual.depth)
380       {
381         return_val = (GdkVisual*) &(visuals[i]);
382         break;
383       }
384
385   return return_val;
386 }
387
388 GdkVisual*
389 gdk_visual_get_best_with_type (GdkVisualType visual_type)
390 {
391   GdkVisual *return_val;
392   int i;
393
394   return_val = NULL;
395   for (i = 0; i < nvisuals; i++)
396     if (visual_type == visuals[i].visual.type)
397       {
398         return_val = (GdkVisual*) &(visuals[i]);
399         break;
400       }
401
402   return return_val;
403 }
404
405 GdkVisual*
406 gdk_visual_get_best_with_both (gint          depth,
407                                GdkVisualType visual_type)
408 {
409   GdkVisual *return_val;
410   int i;
411
412   return_val = NULL;
413   for (i = 0; i < nvisuals; i++)
414     if ((depth == visuals[i].visual.depth) &&
415         (visual_type == visuals[i].visual.type))
416       {
417         return_val = (GdkVisual*) &(visuals[i]);
418         break;
419       }
420
421   return return_val;
422 }
423
424 void
425 gdk_query_depths  (gint **depths,
426                    gint  *count)
427 {
428   *count = navailable_depths;
429   *depths = available_depths;
430 }
431
432 void
433 gdk_query_visual_types (GdkVisualType **visual_types,
434                         gint           *count)
435 {
436   *count = navailable_types;
437   *visual_types = available_types;
438 }
439
440 GList*
441 gdk_list_visuals (void)
442 {
443   GList *list;
444   guint i;
445
446   list = NULL;
447   for (i = 0; i < nvisuals; ++i)
448     list = g_list_append (list, (gpointer) &visuals[i]);
449
450   return list;
451 }
452
453 GdkVisual*
454 gdk_visual_lookup (Visual *xvisual)
455 {
456   GdkVisual *visual;
457
458   if (!visual_hash)
459     return NULL;
460
461   visual = g_hash_table_lookup (visual_hash, xvisual);
462   return visual;
463 }
464
465 GdkVisual*
466 gdkx_visual_get (VisualID xvisualid)
467 {
468   int i;
469
470   for (i = 0; i < nvisuals; i++)
471     if (xvisualid == visuals[i].xvisual->visualid)
472       return (GdkVisual*) &visuals[i];
473
474   return NULL;
475 }
476
477 static void
478 gdk_visual_add (GdkVisual *visual)
479 {
480   GdkVisualPrivate *private;
481
482   if (!visual_hash)
483     visual_hash = g_hash_table_new ((GHashFunc) gdk_visual_hash,
484                                     (GCompareFunc) gdk_visual_compare);
485
486   private = (GdkVisualPrivate*) visual;
487
488   g_hash_table_insert (visual_hash, private->xvisual, visual);
489 }
490
491 static void
492 gdk_visual_decompose_mask (gulong  mask,
493                            gint   *shift,
494                            gint   *prec)
495 {
496   *shift = 0;
497   *prec = 0;
498
499   while (!(mask & 0x1))
500     {
501       (*shift)++;
502       mask >>= 1;
503     }
504
505   while (mask & 0x1)
506     {
507       (*prec)++;
508       mask >>= 1;
509     }
510 }
511
512 /* This hash stuff is pretty useless on Windows, as there is only
513    one visual... */
514
515 static guint
516 gdk_visual_hash (Visual *key)
517 {
518   return key->visualid;
519 }
520
521 static gint
522 gdk_visual_compare (Visual *a,
523                     Visual *b)
524 {
525   return (a->visualid == b->visualid);
526 }