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