Split conical gradient images into pixman-conical-gradient.c
[profile/ivi/pixman.git] / pixman / pixman-image.c
1 /*
2  * Copyright © 2000 SuSE, Inc.
3  * Copyright © 2007 Red Hat, Inc.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation, and that the name of SuSE not be used in advertising or
10  * publicity pertaining to distribution of the software without specific,
11  * written prior permission.  SuSE makes no representations about the
12  * suitability of this software for any purpose.  It is provided "as is"
13  * without express or implied warranty.
14  *
15  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
17  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30
31 #include "pixman-private.h"
32
33 #define Alpha(x) ((x) >> 24)
34
35 pixman_bool_t
36 _pixman_init_gradient (gradient_t     *gradient,
37                        const pixman_gradient_stop_t *stops,
38                        int             n_stops)
39 {
40     return_val_if_fail (n_stops > 0, FALSE);
41
42     gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t));
43     if (!gradient->stops)
44         return FALSE;
45
46     memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
47
48     gradient->n_stops = n_stops;
49
50     gradient->stop_range = 0xffff;
51     gradient->color_table = NULL;
52     gradient->color_table_size = 0;
53     gradient->common.class = SOURCE_IMAGE_CLASS_UNKNOWN;
54
55     return TRUE;
56 }
57
58 pixman_image_t *
59 _pixman_image_allocate (void)
60 {
61     pixman_image_t *image = malloc (sizeof (pixman_image_t));
62
63     if (image)
64     {
65         image_common_t *common = &image->common;
66
67         pixman_region32_init (&common->full_region);
68         pixman_region32_init (&common->clip_region);
69         common->src_clip = &common->full_region;
70         common->has_client_clip = FALSE;
71         common->transform = NULL;
72         common->repeat = PIXMAN_REPEAT_NONE;
73         common->filter = PIXMAN_FILTER_NEAREST;
74         common->filter_params = NULL;
75         common->n_filter_params = 0;
76         common->alpha_map = NULL;
77         common->component_alpha = FALSE;
78         common->ref_count = 1;
79         common->read_func = NULL;
80         common->write_func = NULL;
81         common->classify = NULL;
82     }
83
84     return image;
85 }
86
87 source_pict_class_t
88 _pixman_image_classify (pixman_image_t *image,
89                         int             x,
90                         int             y,
91                         int             width,
92                         int             height)
93 {
94     if (image->common.classify)
95         return image->common.classify (image, x, y, width, height);
96     else
97         return SOURCE_IMAGE_CLASS_UNKNOWN;
98 }
99
100 #define READ_ACCESS(f) ((image->common.read_func)? f##_accessors : f)
101
102 static void fbFetchSolid(bits_image_t * image, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits)
103 {
104     uint32_t color;
105     uint32_t *end;
106     fetchPixelProc32 fetch = READ_ACCESS(pixman_fetchPixelProcForPicture32)(image);
107
108     color = fetch(image, 0, 0);
109
110     end = buffer + width;
111     while (buffer < end)
112         *(buffer++) = color;
113 }
114
115 static void fbFetchSolid64(bits_image_t * image, int x, int y, int width, uint64_t *buffer, void *unused, uint32_t unused2)
116 {
117     uint64_t color;
118     uint64_t *end;
119     fetchPixelProc64 fetch = READ_ACCESS(pixman_fetchPixelProcForPicture64)(image);
120
121     color = fetch(image, 0, 0);
122
123     end = buffer + width;
124     while (buffer < end)
125         *(buffer++) = color;
126 }
127
128 static void fbFetch(bits_image_t * image, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits)
129 {
130     fetchProc32 fetch = READ_ACCESS(pixman_fetchProcForPicture32)(image);
131
132     fetch(image, x, y, width, buffer);
133 }
134
135 static void fbFetch64(bits_image_t * image, int x, int y, int width, uint64_t *buffer, void *unused, uint32_t unused2)
136 {
137     fetchProc64 fetch = READ_ACCESS(pixman_fetchProcForPicture64)(image);
138
139     fetch(image, x, y, width, buffer);
140 }
141
142 scanFetchProc
143 _pixman_image_get_fetcher (pixman_image_t *image,
144                            int             wide)
145 {
146     if (IS_SOURCE_IMAGE (image))
147     {
148         if (wide)
149             return (scanFetchProc)pixmanFetchSourcePict64;
150         else
151             return (scanFetchProc)pixmanFetchSourcePict;
152     }
153     else
154     {
155         bits_image_t *bits = (bits_image_t *)image;
156
157         if (bits->common.alpha_map)
158         {
159             if (wide)
160                 return (scanFetchProc)READ_ACCESS(fbFetchExternalAlpha64);
161             else
162                 return (scanFetchProc)READ_ACCESS(fbFetchExternalAlpha);
163         }
164         else if ((bits->common.repeat != PIXMAN_REPEAT_NONE) &&
165                  bits->width == 1 &&
166                  bits->height == 1)
167         {
168             if (wide)
169                 return (scanFetchProc)fbFetchSolid64;
170             else
171                 return (scanFetchProc)fbFetchSolid;
172         }
173         else if (!bits->common.transform && bits->common.filter != PIXMAN_FILTER_CONVOLUTION
174                 && bits->common.repeat != PIXMAN_REPEAT_PAD && bits->common.repeat != PIXMAN_REPEAT_REFLECT)
175         {
176             if (wide)
177                 return (scanFetchProc)fbFetch64;
178             else
179                 return (scanFetchProc)fbFetch;
180         }
181         else
182         {
183             if (wide)
184                 return (scanFetchProc)READ_ACCESS(fbFetchTransformed64);
185             else
186                 return (scanFetchProc)READ_ACCESS(fbFetchTransformed);
187         }
188     }
189 }
190
191
192
193 #define WRITE_ACCESS(f) ((image->common.write_func)? f##_accessors : f)
194
195 static void
196 fbStore(bits_image_t * image, int x, int y, int width, uint32_t *buffer)
197 {
198     uint32_t *bits;
199     int32_t stride;
200     storeProc32 store = WRITE_ACCESS(pixman_storeProcForPicture32)(image);
201     const pixman_indexed_t * indexed = image->indexed;
202
203     bits = image->bits;
204     stride = image->rowstride;
205     bits += y*stride;
206     store((pixman_image_t *)image, bits, buffer, x, width, indexed);
207 }
208
209 static void
210 fbStore64(bits_image_t * image, int x, int y, int width, uint64_t *buffer)
211 {
212     uint32_t *bits;
213     int32_t stride;
214     storeProc64 store = WRITE_ACCESS(pixman_storeProcForPicture64)(image);
215     const pixman_indexed_t * indexed = image->indexed;
216
217     bits = image->bits;
218     stride = image->rowstride;
219     bits += y*stride;
220     store((pixman_image_t *)image, bits, buffer, x, width, indexed);
221 }
222
223 scanStoreProc
224 _pixman_image_get_storer (pixman_image_t *image,
225                           int             wide)
226 {
227     if (image->common.alpha_map)
228     {
229         if (wide)
230             return (scanStoreProc)WRITE_ACCESS(fbStoreExternalAlpha64);
231         else
232             return (scanStoreProc)WRITE_ACCESS(fbStoreExternalAlpha);
233     }
234     else
235     {
236         if (wide)
237             return (scanStoreProc)fbStore64;
238         else
239             return (scanStoreProc)fbStore;
240     }
241 }
242
243 /* Ref Counting */
244 PIXMAN_EXPORT pixman_image_t *
245 pixman_image_ref (pixman_image_t *image)
246 {
247     image->common.ref_count++;
248
249     return image;
250 }
251
252 /* returns TRUE when the image is freed */
253 PIXMAN_EXPORT pixman_bool_t
254 pixman_image_unref (pixman_image_t *image)
255 {
256     image_common_t *common = (image_common_t *)image;
257
258     common->ref_count--;
259
260     if (common->ref_count == 0)
261     {
262         pixman_region32_fini (&common->clip_region);
263         pixman_region32_fini (&common->full_region);
264
265         if (common->transform)
266             free (common->transform);
267
268         if (common->filter_params)
269             free (common->filter_params);
270
271         if (common->alpha_map)
272             pixman_image_unref ((pixman_image_t *)common->alpha_map);
273
274 #if 0
275         if (image->type == BITS && image->bits.indexed)
276             free (image->bits.indexed);
277 #endif
278
279 #if 0
280         memset (image, 0xaa, sizeof (pixman_image_t));
281 #endif
282         if (image->type == LINEAR || image->type == RADIAL || image->type == CONICAL)
283         {
284             if (image->gradient.stops)
285                 free (image->gradient.stops);
286         }
287
288
289         if (image->type == BITS && image->bits.free_me)
290             free (image->bits.free_me);
291
292         free (image);
293
294         return TRUE;
295     }
296
297     return FALSE;
298 }
299
300 /* Constructors */
301
302 static uint32_t *
303 create_bits (pixman_format_code_t format,
304              int                  width,
305              int                  height,
306              int                 *rowstride_bytes)
307 {
308     int stride;
309     int buf_size;
310     int bpp;
311
312     /* what follows is a long-winded way, avoiding any possibility of integer
313      * overflows, of saying:
314      * stride = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (uint32_t);
315      */
316
317     bpp = PIXMAN_FORMAT_BPP (format);
318     if (pixman_multiply_overflows_int (width, bpp))
319         return NULL;
320
321     stride = width * bpp;
322     if (pixman_addition_overflows_int (stride, FB_MASK))
323         return NULL;
324
325     stride += FB_MASK;
326     stride >>= FB_SHIFT;
327
328 #if FB_SHIFT < 2
329     if (pixman_multiply_overflows_int (stride, sizeof (uint32_t)))
330         return NULL;
331 #endif
332     stride *= sizeof (uint32_t);
333
334     if (pixman_multiply_overflows_int (height, stride))
335         return NULL;
336
337     buf_size = height * stride;
338
339     if (rowstride_bytes)
340         *rowstride_bytes = stride;
341
342     return calloc (buf_size, 1);
343 }
344
345 static void
346 reset_clip_region (pixman_image_t *image)
347 {
348     pixman_region32_fini (&image->common.clip_region);
349
350     if (image->type == BITS)
351     {
352         pixman_region32_init_rect (&image->common.clip_region, 0, 0,
353                                    image->bits.width, image->bits.height);
354     }
355     else
356     {
357         pixman_region32_init (&image->common.clip_region);
358     }
359 }
360
361 PIXMAN_EXPORT pixman_image_t *
362 pixman_image_create_bits (pixman_format_code_t  format,
363                           int                   width,
364                           int                   height,
365                           uint32_t             *bits,
366                           int                   rowstride_bytes)
367 {
368     pixman_image_t *image;
369     uint32_t *free_me = NULL;
370
371     /* must be a whole number of uint32_t's
372      */
373     return_val_if_fail (bits == NULL ||
374                         (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
375
376     if (!bits && width && height)
377     {
378         free_me = bits = create_bits (format, width, height, &rowstride_bytes);
379         if (!bits)
380             return NULL;
381     }
382
383     image = _pixman_image_allocate();
384
385     if (!image) {
386         if (free_me)
387             free (free_me);
388         return NULL;
389     }
390     
391     image->type = BITS;
392     image->bits.format = format;
393     image->bits.width = width;
394     image->bits.height = height;
395     image->bits.bits = bits;
396     image->bits.free_me = free_me;
397
398     image->bits.rowstride = rowstride_bytes / (int) sizeof (uint32_t); /* we store it in number
399                                                                   * of uint32_t's
400                                                                   */
401     image->bits.indexed = NULL;
402
403     pixman_region32_fini (&image->common.full_region);
404     pixman_region32_init_rect (&image->common.full_region, 0, 0,
405                                image->bits.width, image->bits.height);
406
407     reset_clip_region (image);
408     return image;
409 }
410
411 PIXMAN_EXPORT pixman_bool_t
412 pixman_image_set_clip_region32 (pixman_image_t *image,
413                                 pixman_region32_t *region)
414 {
415     image_common_t *common = (image_common_t *)image;
416
417     if (region)
418     {
419         return pixman_region32_copy (&common->clip_region, region);
420     }
421     else
422     {
423         reset_clip_region (image);
424
425         return TRUE;
426     }
427 }
428
429
430 PIXMAN_EXPORT pixman_bool_t
431 pixman_image_set_clip_region (pixman_image_t    *image,
432                               pixman_region16_t *region)
433 {
434     image_common_t *common = (image_common_t *)image;
435
436     if (region)
437     {
438         return pixman_region32_copy_from_region16 (&common->clip_region, region);
439     }
440     else
441     {
442         reset_clip_region (image);
443
444         return TRUE;
445     }
446 }
447
448 /* Sets whether the clip region includes a clip region set by the client
449  */
450 PIXMAN_EXPORT void
451 pixman_image_set_has_client_clip (pixman_image_t *image,
452                                   pixman_bool_t   client_clip)
453 {
454     image->common.has_client_clip = client_clip;
455 }
456
457 PIXMAN_EXPORT pixman_bool_t
458 pixman_image_set_transform (pixman_image_t           *image,
459                             const pixman_transform_t *transform)
460 {
461     static const pixman_transform_t id =
462     {
463         { { pixman_fixed_1, 0, 0 },
464           { 0, pixman_fixed_1, 0 },
465           { 0, 0, pixman_fixed_1 }
466         }
467     };
468
469     image_common_t *common = (image_common_t *)image;
470
471     if (common->transform == transform)
472         return TRUE;
473
474     if (memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
475     {
476         free(common->transform);
477         common->transform = NULL;
478         return TRUE;
479     }
480
481     if (common->transform == NULL)
482         common->transform = malloc (sizeof (pixman_transform_t));
483     if (common->transform == NULL)
484         return FALSE;
485
486     memcpy(common->transform, transform, sizeof(pixman_transform_t));
487
488     return TRUE;
489 }
490
491 PIXMAN_EXPORT void
492 pixman_image_set_repeat (pixman_image_t  *image,
493                          pixman_repeat_t  repeat)
494 {
495     image->common.repeat = repeat;
496 }
497
498 PIXMAN_EXPORT pixman_bool_t
499 pixman_image_set_filter (pixman_image_t       *image,
500                          pixman_filter_t       filter,
501                          const pixman_fixed_t *params,
502                          int                   n_params)
503 {
504     image_common_t *common = (image_common_t *)image;
505     pixman_fixed_t *new_params;
506
507     if (params == common->filter_params && filter == common->filter)
508         return TRUE;
509
510     new_params = NULL;
511     if (params)
512     {
513         new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
514         if (!new_params)
515             return FALSE;
516
517         memcpy (new_params,
518                 params, n_params * sizeof (pixman_fixed_t));
519     }
520
521     common->filter = filter;
522
523     if (common->filter_params)
524         free (common->filter_params);
525
526     common->filter_params = new_params;
527     common->n_filter_params = n_params;
528     return TRUE;
529 }
530
531 PIXMAN_EXPORT void
532 pixman_image_set_source_clipping (pixman_image_t  *image,
533                                   pixman_bool_t    source_clipping)
534 {
535     image_common_t *common = &image->common;
536
537     if (source_clipping)
538         common->src_clip = &common->clip_region;
539     else
540         common->src_clip = &common->full_region;
541 }
542
543 /* Unlike all the other property setters, this function does not
544  * copy the content of indexed. Doing this copying is simply
545  * way, way too expensive.
546  */
547 PIXMAN_EXPORT void
548 pixman_image_set_indexed (pixman_image_t         *image,
549                           const pixman_indexed_t *indexed)
550 {
551     bits_image_t *bits = (bits_image_t *)image;
552
553     bits->indexed = indexed;
554 }
555
556 PIXMAN_EXPORT void
557 pixman_image_set_alpha_map (pixman_image_t *image,
558                             pixman_image_t *alpha_map,
559                             int16_t         x,
560                             int16_t         y)
561 {
562     image_common_t *common = (image_common_t *)image;
563
564     return_if_fail (!alpha_map || alpha_map->type == BITS);
565
566     if (common->alpha_map != (bits_image_t *)alpha_map)
567     {
568         if (common->alpha_map)
569             pixman_image_unref ((pixman_image_t *)common->alpha_map);
570
571         if (alpha_map)
572             common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
573         else
574             common->alpha_map = NULL;
575     }
576
577     common->alpha_origin.x = x;
578     common->alpha_origin.y = y;
579 }
580
581 PIXMAN_EXPORT void
582 pixman_image_set_component_alpha   (pixman_image_t       *image,
583                                     pixman_bool_t         component_alpha)
584 {
585     image->common.component_alpha = component_alpha;
586 }
587
588
589 PIXMAN_EXPORT void
590 pixman_image_set_accessors (pixman_image_t             *image,
591                             pixman_read_memory_func_t   read_func,
592                             pixman_write_memory_func_t  write_func)
593 {
594     return_if_fail (image != NULL);
595
596     image->common.read_func = read_func;
597     image->common.write_func = write_func;
598 }
599
600 PIXMAN_EXPORT uint32_t *
601 pixman_image_get_data (pixman_image_t *image)
602 {
603     if (image->type == BITS)
604         return image->bits.bits;
605
606     return NULL;
607 }
608
609 PIXMAN_EXPORT int
610 pixman_image_get_width (pixman_image_t *image)
611 {
612     if (image->type == BITS)
613         return image->bits.width;
614
615     return 0;
616 }
617
618 PIXMAN_EXPORT int
619 pixman_image_get_height (pixman_image_t *image)
620 {
621     if (image->type == BITS)
622         return image->bits.height;
623
624     return 0;
625 }
626
627 PIXMAN_EXPORT int
628 pixman_image_get_stride (pixman_image_t *image)
629 {
630     if (image->type == BITS)
631         return image->bits.rowstride * (int) sizeof (uint32_t);
632
633     return 0;
634 }
635
636 PIXMAN_EXPORT int
637 pixman_image_get_depth (pixman_image_t *image)
638 {
639     if (image->type == BITS)
640         return PIXMAN_FORMAT_DEPTH (image->bits.format);
641
642     return 0;
643 }
644
645 static uint32_t
646 color_to_uint32 (const pixman_color_t *color)
647 {
648     return
649         (color->alpha >> 8 << 24) |
650         (color->red >> 8 << 16) |
651         (color->green & 0xff00) |
652         (color->blue >> 8);
653 }
654
655 static pixman_bool_t
656 color_to_pixel (pixman_color_t *color,
657                 uint32_t       *pixel,
658                 pixman_format_code_t format)
659 {
660     uint32_t c = color_to_uint32 (color);
661
662     if (!(format == PIXMAN_a8r8g8b8     ||
663           format == PIXMAN_x8r8g8b8     ||
664           format == PIXMAN_a8b8g8r8     ||
665           format == PIXMAN_x8b8g8r8     ||
666           format == PIXMAN_b8g8r8a8     ||
667           format == PIXMAN_b8g8r8x8     ||
668           format == PIXMAN_r5g6b5       ||
669           format == PIXMAN_b5g6r5       ||
670           format == PIXMAN_a8))
671     {
672         return FALSE;
673     }
674
675     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
676     {
677         c = ((c & 0xff000000) >>  0) |
678             ((c & 0x00ff0000) >> 16) |
679             ((c & 0x0000ff00) >>  0) |
680             ((c & 0x000000ff) << 16);
681     }
682     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
683     {
684         c = ((c & 0xff000000) >> 24) |
685             ((c & 0x00ff0000) >>  8) |
686             ((c & 0x0000ff00) <<  8) |
687             ((c & 0x000000ff) << 24);
688     }
689
690     if (format == PIXMAN_a8)
691         c = c >> 24;
692     else if (format == PIXMAN_r5g6b5 ||
693              format == PIXMAN_b5g6r5)
694         c = cvt8888to0565 (c);
695
696 #if 0
697     printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
698     printf ("pixel: %x\n", c);
699 #endif
700
701     *pixel = c;
702     return TRUE;
703 }
704
705 PIXMAN_EXPORT pixman_bool_t
706 pixman_image_fill_rectangles (pixman_op_t                   op,
707                               pixman_image_t               *dest,
708                               pixman_color_t               *color,
709                               int                           n_rects,
710                               const pixman_rectangle16_t   *rects)
711 {
712     pixman_image_t *solid;
713     pixman_color_t c;
714     int i;
715
716     if (color->alpha == 0xffff)
717     {
718         if (op == PIXMAN_OP_OVER)
719             op = PIXMAN_OP_SRC;
720     }
721
722     if (op == PIXMAN_OP_CLEAR)
723     {
724         c.red = 0;
725         c.green = 0;
726         c.blue = 0;
727         c.alpha = 0;
728
729         color = &c;
730
731         op = PIXMAN_OP_SRC;
732     }
733
734     if (op == PIXMAN_OP_SRC)
735     {
736         uint32_t pixel;
737
738         if (color_to_pixel (color, &pixel, dest->bits.format))
739         {
740             for (i = 0; i < n_rects; ++i)
741             {
742                 pixman_region32_t fill_region;
743                 int n_boxes, j;
744                 pixman_box32_t *boxes;
745
746                 pixman_region32_init_rect (&fill_region, rects[i].x, rects[i].y, rects[i].width, rects[i].height);
747                 if (!pixman_region32_intersect (&fill_region,
748                                                 &fill_region,
749                                                 &dest->common.clip_region))
750                     return FALSE;
751
752
753                 boxes = pixman_region32_rectangles (&fill_region, &n_boxes);
754                 for (j = 0; j < n_boxes; ++j)
755                 {
756                     const pixman_box32_t *box = &(boxes[j]);
757                     pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
758                                  box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1,
759                                  pixel);
760                 }
761
762                 pixman_region32_fini (&fill_region);
763             }
764             return TRUE;
765         }
766     }
767
768     solid = pixman_image_create_solid_fill (color);
769     if (!solid)
770         return FALSE;
771
772     for (i = 0; i < n_rects; ++i)
773     {
774         const pixman_rectangle16_t *rect = &(rects[i]);
775
776         pixman_image_composite (op, solid, NULL, dest,
777                                 0, 0, 0, 0,
778                                 rect->x, rect->y,
779                                 rect->width, rect->height);
780     }
781
782     pixman_image_unref (solid);
783
784     return TRUE;
785 }
786
787 pixman_bool_t
788 pixman_image_can_get_solid (pixman_image_t *image)
789 {
790     if (image->type == SOLID)
791         return TRUE;
792
793     if (image->type != BITS     ||
794         image->bits.width != 1  ||
795         image->bits.height != 1)
796     {
797         return FALSE;
798     }
799
800     if (image->common.repeat != PIXMAN_REPEAT_NORMAL)
801         return FALSE;
802
803     switch (image->bits.format)
804     {
805     case PIXMAN_a8r8g8b8:
806     case PIXMAN_x8r8g8b8:
807     case PIXMAN_a8b8g8r8:
808     case PIXMAN_x8b8g8r8:
809     case PIXMAN_b8g8r8a8:
810     case PIXMAN_b8g8r8x8:
811     case PIXMAN_r8g8b8:
812     case PIXMAN_b8g8r8:
813     case PIXMAN_r5g6b5:
814     case PIXMAN_b5g6r5:
815         return TRUE;
816     default:
817         return FALSE;
818     }
819 }
820
821 pixman_bool_t
822 pixman_image_is_opaque(pixman_image_t *image)
823 {
824     int i = 0;
825     int gradientNumberOfColors = 0;
826
827     if(image->common.alpha_map)
828         return FALSE;
829
830     switch(image->type)
831     {
832     case BITS:
833         if(PIXMAN_FORMAT_A(image->bits.format))
834             return FALSE;
835         break;
836
837     case LINEAR:
838     case CONICAL:
839     case RADIAL:
840         gradientNumberOfColors = image->gradient.n_stops;
841         i=0;
842         while(i<gradientNumberOfColors)
843         {
844             if(image->gradient.stops[i].color.alpha != 0xffff)
845                 return FALSE;
846             i++;
847         }
848         break;
849
850     case SOLID:
851          if(Alpha(image->solid.color) != 0xff)
852             return FALSE;
853         break;
854     }
855
856     /* Convolution filters can introduce translucency if the sum of the weights
857        is lower than 1. */
858     if (image->common.filter == PIXMAN_FILTER_CONVOLUTION)
859          return FALSE;
860
861     if (image->common.repeat == PIXMAN_REPEAT_NONE)
862     {
863         if (image->common.filter != PIXMAN_FILTER_NEAREST)
864             return FALSE;
865
866         if (image->common.transform)
867             return FALSE;
868
869         /* Gradients do not necessarily cover the entire compositing area */
870         if (image->type == LINEAR || image->type == CONICAL || image->type == RADIAL)
871             return FALSE;
872     }
873
874      return TRUE;
875 }