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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser 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-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.
23  */
24 
25 /*
26  * GTK+ DirectFB backend
27  * Copyright (C) 2001-2002  convergence integrated media GmbH
28  * Copyright (C) 2002       convergence GmbH
29  * Written by Denis Oliver Kropp <dok@convergence.de> and
30  *            Sven Neumann <sven@convergence.de>
31  */
32 
33 #include "config.h"
34 #include "gdk.h"
35 
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 
41 #include "gdkcolor.h"
42 #include "gdkinternals.h"
43 #include "gdkdirectfb.h"
44 #include "gdkprivate-directfb.h"
45 #include "gdkalias.h"
46 
47 
48 typedef struct {
49   GdkColorInfo     *info;
50   IDirectFBPalette *palette;
51 } GdkColormapPrivateDirectFB;
52 
53 
54 static void  gdk_colormap_finalize (GObject *object);
55 
56 static gint  gdk_colormap_alloc_pseudocolors (GdkColormap *colormap,
57                                               GdkColor    *colors,
58                                               gint         ncolors,
59                                               gboolean     writeable,
60                                               gboolean     best_match,
61                                               gboolean    *success);
62 static void  gdk_directfb_allocate_color_key (GdkColormap *colormap);
63 
64 
G_DEFINE_TYPE(GdkColormap,gdk_colormap,G_TYPE_OBJECT)65 G_DEFINE_TYPE (GdkColormap, gdk_colormap, G_TYPE_OBJECT)
66 
67 static void
68 gdk_colormap_init (GdkColormap *colormap)
69 {
70   colormap->size           = 0;
71   colormap->colors         = NULL;
72   colormap->windowing_data = NULL;
73 }
74 
75 static void
gdk_colormap_class_init(GdkColormapClass * klass)76 gdk_colormap_class_init (GdkColormapClass *klass)
77 {
78   GObjectClass *object_class = G_OBJECT_CLASS (klass);
79 
80   object_class->finalize = gdk_colormap_finalize;
81 }
82 
83 static void
gdk_colormap_finalize(GObject * object)84 gdk_colormap_finalize (GObject *object)
85 {
86   GdkColormap                *colormap = GDK_COLORMAP (object);
87   GdkColormapPrivateDirectFB *private  = colormap->windowing_data;
88 
89   g_free (colormap->colors);
90 
91   if (private)
92     {
93       g_free (private->info);
94 
95       if (private->palette)
96         private->palette->Release (private->palette);
97 
98       g_free (private);
99       colormap->windowing_data = NULL;
100     }
101 
102   G_OBJECT_CLASS (gdk_colormap_parent_class)->finalize (object);
103 }
104 
105 GdkColormap*
gdk_colormap_new(GdkVisual * visual,gboolean private_cmap)106 gdk_colormap_new (GdkVisual *visual,
107                   gboolean   private_cmap)
108 {
109   GdkColormap *colormap;
110   gint         i;
111 
112   g_return_val_if_fail (visual != NULL, NULL);
113 
114   colormap = g_object_new (gdk_colormap_get_type (), NULL);
115   colormap->visual = visual;
116   colormap->size   = visual->colormap_size;
117 
118   switch (visual->type)
119     {
120     case GDK_VISUAL_PSEUDO_COLOR:
121       {
122         IDirectFB                  *dfb = _gdk_display->directfb;
123         IDirectFBPalette           *palette;
124         GdkColormapPrivateDirectFB *private;
125         DFBPaletteDescription       dsc;
126 
127         dsc.flags = DPDESC_SIZE;
128         dsc.size  = colormap->size;
129         if (!dfb->CreatePalette (dfb, &dsc, &palette))
130           return NULL;
131 
132         colormap->colors = g_new0 (GdkColor, colormap->size);
133 
134         private = g_new0 (GdkColormapPrivateDirectFB, 1);
135         private->info = g_new0 (GdkColorInfo, colormap->size);
136 
137 	if (visual == gdk_visual_get_system ())
138 	  {
139             /* save the first (transparent) palette entry */
140             private->info[0].ref_count++;
141           }
142 
143         private->palette = palette;
144 
145         colormap->windowing_data = private;
146 
147         gdk_directfb_allocate_color_key (colormap);
148       }
149       break;
150 
151     case GDK_VISUAL_STATIC_COLOR:
152       colormap->colors = g_new0 (GdkColor, colormap->size);
153       for (i = 0; i < colormap->size; i++)
154         {
155           GdkColor *color = colormap->colors + i;
156 
157           color->pixel = i;
158           color->red   = (i & 0xE0) <<  8 | (i & 0xE0);
159           color->green = (i & 0x1C) << 11 | (i & 0x1C) << 3;
160           color->blue  = (i & 0x03) << 14 | (i & 0x03) << 6;
161         }
162       break;
163 
164     default:
165       break;
166     }
167 
168   return colormap;
169 }
170 
171 GdkScreen*
gdk_colormap_get_screen(GdkColormap * cmap)172 gdk_colormap_get_screen (GdkColormap *cmap)
173 {
174   return _gdk_screen;
175 }
176 
177 GdkColormap*
gdk_screen_get_system_colormap(GdkScreen * screen)178 gdk_screen_get_system_colormap (GdkScreen *screen)
179 {
180   static GdkColormap *colormap = NULL;
181 
182   if (!colormap)
183     {
184       GdkVisual *visual = gdk_visual_get_system ();
185 
186       /* special case PSEUDO_COLOR to use the system palette */
187       if (visual->type == GDK_VISUAL_PSEUDO_COLOR)
188         {
189           GdkColormapPrivateDirectFB *private;
190           IDirectFBSurface           *surface;
191 
192           colormap = g_object_new (gdk_colormap_get_type (), NULL);
193 
194           colormap->visual = visual;
195           colormap->size   = visual->colormap_size;
196           colormap->colors = g_new0 (GdkColor, colormap->size);
197 
198           private = g_new0 (GdkColormapPrivateDirectFB, 1);
199           private->info = g_new0 (GdkColorInfo, colormap->size);
200 
201           surface = GDK_WINDOW_IMPL_DIRECTFB (
202                         GDK_WINDOW_OBJECT (_gdk_parent_root)->impl)->drawable.surface;
203           surface->GetPalette (surface, &private->palette);
204 
205           colormap->windowing_data = private;
206 
207           /* save the first (transparent) palette entry */
208           private->info[0].ref_count++;
209 
210           gdk_directfb_allocate_color_key (colormap);
211         }
212       else
213         {
214           colormap = gdk_colormap_new (visual, FALSE);
215         }
216     }
217 
218   return colormap;
219 }
220 
221 gint
gdk_colormap_get_system_size(void)222 gdk_colormap_get_system_size (void)
223 {
224   GdkVisual *visual;
225 
226   visual = gdk_visual_get_system ();
227 
228   return visual->colormap_size;
229 }
230 
231 void
gdk_colormap_change(GdkColormap * colormap,gint ncolors)232 gdk_colormap_change (GdkColormap *colormap,
233                      gint         ncolors)
234 {
235   g_message ("gdk_colormap_change() is deprecated and unimplemented");
236 }
237 
238 gboolean
gdk_colors_alloc(GdkColormap * colormap,gboolean contiguous,gulong * planes,gint nplanes,gulong * pixels,gint npixels)239 gdk_colors_alloc (GdkColormap   *colormap,
240                   gboolean       contiguous,
241                   gulong        *planes,
242                   gint           nplanes,
243                   gulong        *pixels,
244                   gint           npixels)
245 {
246   /* g_message ("gdk_colors_alloc() is deprecated and unimplemented"); */
247 
248   return TRUE;  /* return TRUE here to make GdkRGB happy */
249 }
250 
251 void
gdk_colors_free(GdkColormap * colormap,gulong * in_pixels,gint in_npixels,gulong planes)252 gdk_colors_free (GdkColormap *colormap,
253                  gulong      *in_pixels,
254                  gint         in_npixels,
255                  gulong       planes)
256 {
257   /* g_message ("gdk_colors_free() is deprecated and unimplemented"); */
258 }
259 
260 void
gdk_colormap_free_colors(GdkColormap * colormap,const GdkColor * colors,gint ncolors)261 gdk_colormap_free_colors (GdkColormap    *colormap,
262                           const GdkColor *colors,
263                           gint            ncolors)
264 {
265   GdkColormapPrivateDirectFB *private;
266   gint                        i;
267 
268   g_return_if_fail (GDK_IS_COLORMAP (colormap));
269   g_return_if_fail (colors != NULL);
270 
271   private = colormap->windowing_data;
272   if (!private)
273     return;
274 
275   for (i = 0; i < ncolors; i++)
276     {
277       gint  index = colors[i].pixel;
278 
279       if (index < 0 || index >= colormap->size)
280         continue;
281 
282       if (private->info[index].ref_count)
283         private->info[index].ref_count--;
284     }
285 }
286 
287 gint
gdk_colormap_alloc_colors(GdkColormap * colormap,GdkColor * colors,gint ncolors,gboolean writeable,gboolean best_match,gboolean * success)288 gdk_colormap_alloc_colors (GdkColormap *colormap,
289                            GdkColor    *colors,
290                            gint         ncolors,
291                            gboolean     writeable,
292                            gboolean     best_match,
293                            gboolean    *success)
294 {
295   GdkVisual *visual;
296   gint       i;
297 
298   g_return_val_if_fail (GDK_IS_COLORMAP (colormap), 0);
299   g_return_val_if_fail (colors != NULL, 0);
300   g_return_val_if_fail (success != NULL, 0);
301 
302   switch (colormap->visual->type)
303     {
304     case GDK_VISUAL_TRUE_COLOR:
305       visual = colormap->visual;
306 
307       for (i = 0; i < ncolors; i++)
308         {
309           colors[i].pixel =
310             (((colors[i].red
311                >> (16 - visual->red_prec))   << visual->red_shift)   +
312              ((colors[i].green
313                >> (16 - visual->green_prec)) << visual->green_shift) +
314              ((colors[i].blue
315                >> (16 - visual->blue_prec))  << visual->blue_shift));
316 
317           success[i] = TRUE;
318         }
319       break;
320 
321     case GDK_VISUAL_PSEUDO_COLOR:
322       return gdk_colormap_alloc_pseudocolors (colormap,
323                                               colors, ncolors,
324                                               writeable, best_match,
325                                               success);
326       break;
327 
328     case GDK_VISUAL_STATIC_COLOR:
329       for (i = 0; i < ncolors; i++)
330         {
331           colors[i].pixel = (((colors[i].red   & 0xE000) >> 8)  |
332                              ((colors[i].green & 0xE000) >> 11) |
333                              ((colors[i].blue  & 0xC000) >> 14));
334           success[i] = TRUE;
335         }
336       break;
337 
338     default:
339       for (i = 0; i < ncolors; i++)
340         success[i] = FALSE;
341       break;
342     }
343 
344   return 0;
345 }
346 
347 gboolean
gdk_color_change(GdkColormap * colormap,GdkColor * color)348 gdk_color_change (GdkColormap *colormap,
349                   GdkColor    *color)
350 {
351   GdkColormapPrivateDirectFB *private;
352   IDirectFBPalette           *palette;
353 
354   g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
355   g_return_val_if_fail (color != NULL, FALSE);
356 
357   private = colormap->windowing_data;
358   if (!private)
359     return FALSE;
360 
361   palette = private->palette;
362   if (!palette)
363     return FALSE;
364 
365   if (color->pixel < 0 || color->pixel >= colormap->size)
366     return FALSE;
367 
368   if (private->info[color->pixel].flags & GDK_COLOR_WRITEABLE)
369     {
370       DFBColor  entry = { 0xFF,
371                           color->red   >> 8,
372                           color->green >> 8,
373                           color->blue  >> 8 };
374 
375       if (palette->SetEntries (palette, &entry, 1, color->pixel) != DFB_OK)
376         return FALSE;
377 
378       colormap->colors[color->pixel] = *color;
379       return TRUE;
380     }
381 
382   return FALSE;
383 }
384 
385 void
gdk_colormap_query_color(GdkColormap * colormap,gulong pixel,GdkColor * result)386 gdk_colormap_query_color (GdkColormap *colormap,
387                           gulong       pixel,
388                           GdkColor    *result)
389 {
390   GdkVisual *visual;
391 
392   g_return_if_fail (GDK_IS_COLORMAP (colormap));
393 
394   visual = gdk_colormap_get_visual (colormap);
395 
396   switch (visual->type)
397     {
398     case GDK_VISUAL_TRUE_COLOR:
399       result->red = 65535. *
400         (gdouble)((pixel & visual->red_mask) >> visual->red_shift) /
401         ((1 << visual->red_prec) - 1);
402 
403       result->green = 65535. *
404         (gdouble)((pixel & visual->green_mask) >> visual->green_shift) /
405         ((1 << visual->green_prec) - 1);
406 
407       result->blue = 65535. *
408         (gdouble)((pixel & visual->blue_mask) >> visual->blue_shift) /
409         ((1 << visual->blue_prec) - 1);
410       break;
411 
412     case GDK_VISUAL_STATIC_COLOR:
413     case GDK_VISUAL_PSEUDO_COLOR:
414       if (pixel >= 0 && pixel < colormap->size)
415         {
416           result->red   = colormap->colors[pixel].red;
417           result->green = colormap->colors[pixel].green;
418           result->blue  = colormap->colors[pixel].blue;
419         }
420       else
421         g_warning ("gdk_colormap_query_color: pixel outside colormap");
422       break;
423 
424     case GDK_VISUAL_DIRECT_COLOR:
425     case GDK_VISUAL_GRAYSCALE:
426     case GDK_VISUAL_STATIC_GRAY:
427       /* unsupported */
428       g_assert_not_reached ();
429       break;
430     }
431 }
432 
433 IDirectFBPalette *
gdk_directfb_colormap_get_palette(GdkColormap * colormap)434 gdk_directfb_colormap_get_palette (GdkColormap *colormap)
435 {
436   GdkColormapPrivateDirectFB *private;
437 
438   g_return_val_if_fail (GDK_IS_COLORMAP (colormap), NULL);
439 
440   private = colormap->windowing_data;
441 
442   if (private && private->palette)
443     return private->palette;
444   else
445     return NULL;
446 }
447 
448 static gint
gdk_colormap_alloc_pseudocolors(GdkColormap * colormap,GdkColor * colors,gint ncolors,gboolean writeable,gboolean best_match,gboolean * success)449 gdk_colormap_alloc_pseudocolors (GdkColormap *colormap,
450                                  GdkColor    *colors,
451                                  gint         ncolors,
452                                  gboolean     writeable,
453                                  gboolean     best_match,
454                                  gboolean    *success)
455 {
456   GdkColormapPrivateDirectFB *private = colormap->windowing_data;
457   IDirectFBPalette           *palette;
458   gint                        i, j;
459   gint                        remaining = ncolors;
460 
461   palette = private->palette;
462 
463   for (i = 0; i < ncolors; i++)
464     {
465       guint     index;
466       DFBColor  lookup = { 0xFF,
467                            colors[i].red   >> 8,
468                            colors[i].green >> 8,
469                            colors[i].blue  >> 8 };
470 
471       success[i] = FALSE;
472 
473       if (writeable)
474         {
475           /* look for an empty slot and allocate a new color */
476           for (j = 0; j < colormap->size; j++)
477             if (private->info[j].ref_count == 0)
478               {
479                 index = j;
480 
481                 palette->SetEntries (palette, &lookup, 1, index);
482 
483                 private->info[index].flags = GDK_COLOR_WRITEABLE;
484 
485                 colors[i].pixel = index;
486                 colormap->colors[index] = colors[i];
487 
488                 goto allocated;
489               }
490         }
491       else
492         {
493           palette->FindBestMatch (palette,
494                                   lookup.r, lookup.g, lookup.b, lookup.a,
495                                   &index);
496 
497           if (index < 0 || index > colormap->size)
498             continue;
499 
500           /* check if we have an exact (non-writeable) match */
501           if (private->info[index].ref_count &&
502               !(private->info[index].flags & GDK_COLOR_WRITEABLE))
503             {
504               DFBColor  entry;
505 
506               palette->GetEntries (palette, &entry, 1, index);
507 
508               if (entry.a == 0xFF &&
509                   entry.r == lookup.r && entry.g == lookup.g && entry.b == lookup.b)
510                 {
511                   colors[i].pixel = index;
512 
513                   goto allocated;
514                 }
515             }
516 
517           /* look for an empty slot and allocate a new color */
518           for (j = 0; j < colormap->size; j++)
519             if (private->info[j].ref_count == 0)
520               {
521                 index = j;
522 
523                 palette->SetEntries (palette, &lookup, 1, index);
524     		private->info[index].flags = 0;
525 
526                 colors[i].pixel = index;
527                 colormap->colors[index] = colors[i];
528 
529                 goto allocated;
530               }
531 
532           /* if that failed, use the best match */
533           if (best_match &&
534               !(private->info[index].flags & GDK_COLOR_WRITEABLE))
535             {
536 #if 0
537                g_print ("best match for (%d %d %d)  ",
538                        colormap->colors[index].red,
539                        colormap->colors[index].green,
540                        colormap->colors[index].blue);
541 #endif
542 
543               colors[i].pixel = index;
544 
545               goto allocated;
546             }
547         }
548 
549       /* if we got here, all attempts failed */
550       continue;
551 
552     allocated:
553       private->info[index].ref_count++;
554 
555 #if 0
556       g_print ("cmap %p: allocated (%d %d %d) %d [%d]\n", colormap,
557                 colors[i].red, colors[i].green, colors[i].blue, colors[i].pixel,
558 	        private->info[index].ref_count);
559 #endif
560 
561       success[i] = TRUE;
562       remaining--;
563     }
564 
565   return remaining;
566 }
567 
568 /* dirty hack for color_keying */
569 static void
gdk_directfb_allocate_color_key(GdkColormap * colormap)570 gdk_directfb_allocate_color_key (GdkColormap *colormap)
571 {
572   GdkColormapPrivateDirectFB *private = colormap->windowing_data;
573   IDirectFBPalette           *palette = private->palette;
574 
575   if (!gdk_directfb_enable_color_keying)
576     return;
577 
578   palette->SetEntries (palette, &gdk_directfb_bg_color, 1, 255);
579 
580   colormap->colors[255].pixel = 255;
581   colormap->colors[255].red   = ((gdk_directfb_bg_color_key.r << 8)
582                                  | gdk_directfb_bg_color_key.r);
583   colormap->colors[255].green = ((gdk_directfb_bg_color_key.g << 8)
584                                  | gdk_directfb_bg_color_key.g);
585   colormap->colors[255].blue  = ((gdk_directfb_bg_color_key.b << 8)
586                                  | gdk_directfb_bg_color_key.b);
587 
588   private->info[255].ref_count++;
589 }
590 #define __GDK_COLOR_X11_C__
591 #include "gdkaliasdef.c"
592