Get rid of SOURCE_IMAGE_CLASS_NEITHER again
[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 static source_pict_class_t
36 SourcePictureClassify (pixman_image_t *image,
37                        int             x,
38                        int             y,
39                        int             width,
40                        int             height)
41 {
42     source_image_t *pict = &image->source;
43     
44     pict->class = SOURCE_IMAGE_CLASS_UNKNOWN;
45     
46     if (pict->common.type == SOLID)
47     {
48         pict->class = SOURCE_IMAGE_CLASS_HORIZONTAL;
49     }
50     else if (pict->common.type == LINEAR)
51     {
52         linear_gradient_t *linear = (linear_gradient_t *)pict;
53         pixman_vector_t   v;
54         pixman_fixed_32_32_t l;
55         pixman_fixed_48_16_t dx, dy, a, b, off;
56         pixman_fixed_48_16_t factors[4];
57         int          i;
58
59         dx = linear->p2.x - linear->p1.x;
60         dy = linear->p2.y - linear->p1.y;
61         l = dx * dx + dy * dy;
62         if (l)
63         {
64             a = (dx << 32) / l;
65             b = (dy << 32) / l;
66         }
67         else
68         {
69             a = b = 0;
70         }
71
72         off = (-a * linear->p1.x
73                -b * linear->p1.y) >> 16;
74
75         for (i = 0; i < 3; i++)
76         {
77             v.vector[0] = pixman_int_to_fixed ((i % 2) * (width  - 1) + x);
78             v.vector[1] = pixman_int_to_fixed ((i / 2) * (height - 1) + y);
79             v.vector[2] = pixman_fixed_1;
80
81             if (pict->common.transform)
82             {
83                 if (!pixman_transform_point_3d (pict->common.transform, &v))
84                 {
85                     pict->class = SOURCE_IMAGE_CLASS_UNKNOWN;
86                     goto out;
87                 }
88             }
89
90             factors[i] = ((a * v.vector[0] + b * v.vector[1]) >> 16) + off;
91         }
92
93         if (factors[2] == factors[0])
94             pict->class = SOURCE_IMAGE_CLASS_HORIZONTAL;
95         else if (factors[1] == factors[0])
96             pict->class = SOURCE_IMAGE_CLASS_VERTICAL;
97     }
98
99 out:
100     return pict->class;
101 }
102
103 static void
104 init_source_image (source_image_t *image)
105 {
106     image->class = SOURCE_IMAGE_CLASS_UNKNOWN;
107     image->common.classify = SourcePictureClassify;
108 }
109
110 static pixman_bool_t
111 init_gradient (gradient_t     *gradient,
112                const pixman_gradient_stop_t *stops,
113                int             n_stops)
114 {
115     return_val_if_fail (n_stops > 0, FALSE);
116
117     init_source_image (&gradient->common);
118
119     gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t));
120     if (!gradient->stops)
121         return FALSE;
122
123     memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
124
125     gradient->n_stops = n_stops;
126
127     gradient->stop_range = 0xffff;
128     gradient->color_table = NULL;
129     gradient->color_table_size = 0;
130
131     return TRUE;
132 }
133
134 static uint32_t
135 color_to_uint32 (const pixman_color_t *color)
136 {
137     return
138         (color->alpha >> 8 << 24) |
139         (color->red >> 8 << 16) |
140         (color->green & 0xff00) |
141         (color->blue >> 8);
142 }
143
144 static pixman_image_t *
145 allocate_image (void)
146 {
147     pixman_image_t *image = malloc (sizeof (pixman_image_t));
148
149     if (image)
150     {
151         image_common_t *common = &image->common;
152
153         pixman_region32_init (&common->full_region);
154         pixman_region32_init (&common->clip_region);
155         common->src_clip = &common->full_region;
156         common->has_client_clip = FALSE;
157         common->transform = NULL;
158         common->repeat = PIXMAN_REPEAT_NONE;
159         common->filter = PIXMAN_FILTER_NEAREST;
160         common->filter_params = NULL;
161         common->n_filter_params = 0;
162         common->alpha_map = NULL;
163         common->component_alpha = FALSE;
164         common->ref_count = 1;
165         common->read_func = NULL;
166         common->write_func = NULL;
167         common->classify = NULL;
168     }
169
170     return image;
171 }
172
173 source_pict_class_t
174 _pixman_image_classify (pixman_image_t *image,
175                         int             x,
176                         int             y,
177                         int             width,
178                         int             height)
179 {
180     if (image->common.classify)
181         return image->common.classify (image, x, y, width, height);
182     else
183         return SOURCE_IMAGE_CLASS_UNKNOWN;
184 }
185
186 /* Ref Counting */
187 PIXMAN_EXPORT pixman_image_t *
188 pixman_image_ref (pixman_image_t *image)
189 {
190     image->common.ref_count++;
191
192     return image;
193 }
194
195 /* returns TRUE when the image is freed */
196 PIXMAN_EXPORT pixman_bool_t
197 pixman_image_unref (pixman_image_t *image)
198 {
199     image_common_t *common = (image_common_t *)image;
200
201     common->ref_count--;
202
203     if (common->ref_count == 0)
204     {
205         pixman_region32_fini (&common->clip_region);
206         pixman_region32_fini (&common->full_region);
207
208         if (common->transform)
209             free (common->transform);
210
211         if (common->filter_params)
212             free (common->filter_params);
213
214         if (common->alpha_map)
215             pixman_image_unref ((pixman_image_t *)common->alpha_map);
216
217 #if 0
218         if (image->type == BITS && image->bits.indexed)
219             free (image->bits.indexed);
220 #endif
221
222 #if 0
223         memset (image, 0xaa, sizeof (pixman_image_t));
224 #endif
225         if (image->type == LINEAR || image->type == RADIAL || image->type == CONICAL)
226         {
227             if (image->gradient.stops)
228                 free (image->gradient.stops);
229         }
230
231
232         if (image->type == BITS && image->bits.free_me)
233             free (image->bits.free_me);
234
235         free (image);
236
237         return TRUE;
238     }
239
240     return FALSE;
241 }
242
243 /* Constructors */
244 PIXMAN_EXPORT pixman_image_t *
245 pixman_image_create_solid_fill (pixman_color_t *color)
246 {
247     pixman_image_t *img = allocate_image();
248     if (!img)
249         return NULL;
250
251     init_source_image (&img->solid.common);
252
253     img->type = SOLID;
254     img->solid.color = color_to_uint32 (color);
255
256     return img;
257 }
258
259 PIXMAN_EXPORT pixman_image_t *
260 pixman_image_create_linear_gradient (pixman_point_fixed_t         *p1,
261                                      pixman_point_fixed_t         *p2,
262                                      const pixman_gradient_stop_t *stops,
263                                      int                           n_stops)
264 {
265     pixman_image_t *image;
266     linear_gradient_t *linear;
267
268     return_val_if_fail (n_stops >= 2, NULL);
269
270     image = allocate_image();
271
272     if (!image)
273         return NULL;
274
275     linear = &image->linear;
276
277     if (!init_gradient (&linear->common, stops, n_stops))
278     {
279         free (image);
280         return NULL;
281     }
282
283     linear->p1 = *p1;
284     linear->p2 = *p2;
285
286     image->type = LINEAR;
287
288     return image;
289 }
290
291
292 PIXMAN_EXPORT pixman_image_t *
293 pixman_image_create_radial_gradient (pixman_point_fixed_t         *inner,
294                                      pixman_point_fixed_t         *outer,
295                                      pixman_fixed_t                inner_radius,
296                                      pixman_fixed_t                outer_radius,
297                                      const pixman_gradient_stop_t *stops,
298                                      int                           n_stops)
299 {
300     pixman_image_t *image;
301     radial_gradient_t *radial;
302
303     return_val_if_fail (n_stops >= 2, NULL);
304
305     image = allocate_image();
306
307     if (!image)
308         return NULL;
309
310     radial = &image->radial;
311
312     if (!init_gradient (&radial->common, stops, n_stops))
313     {
314         free (image);
315         return NULL;
316     }
317
318     image->type = RADIAL;
319
320     radial->c1.x = inner->x;
321     radial->c1.y = inner->y;
322     radial->c1.radius = inner_radius;
323     radial->c2.x = outer->x;
324     radial->c2.y = outer->y;
325     radial->c2.radius = outer_radius;
326     radial->cdx = pixman_fixed_to_double (radial->c2.x - radial->c1.x);
327     radial->cdy = pixman_fixed_to_double (radial->c2.y - radial->c1.y);
328     radial->dr = pixman_fixed_to_double (radial->c2.radius - radial->c1.radius);
329     radial->A = (radial->cdx * radial->cdx
330                  + radial->cdy * radial->cdy
331                  - radial->dr  * radial->dr);
332
333     return image;
334 }
335
336 PIXMAN_EXPORT pixman_image_t *
337 pixman_image_create_conical_gradient (pixman_point_fixed_t *center,
338                                       pixman_fixed_t angle,
339                                       const pixman_gradient_stop_t *stops,
340                                       int n_stops)
341 {
342     pixman_image_t *image = allocate_image();
343     conical_gradient_t *conical;
344
345     if (!image)
346         return NULL;
347
348     conical = &image->conical;
349
350     if (!init_gradient (&conical->common, stops, n_stops))
351     {
352         free (image);
353         return NULL;
354     }
355
356     image->type = CONICAL;
357     conical->center = *center;
358     conical->angle = angle;
359
360     return image;
361 }
362
363 static uint32_t *
364 create_bits (pixman_format_code_t format,
365              int                  width,
366              int                  height,
367              int                 *rowstride_bytes)
368 {
369     int stride;
370     int buf_size;
371     int bpp;
372
373     /* what follows is a long-winded way, avoiding any possibility of integer
374      * overflows, of saying:
375      * stride = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (uint32_t);
376      */
377
378     bpp = PIXMAN_FORMAT_BPP (format);
379     if (pixman_multiply_overflows_int (width, bpp))
380         return NULL;
381
382     stride = width * bpp;
383     if (pixman_addition_overflows_int (stride, FB_MASK))
384         return NULL;
385
386     stride += FB_MASK;
387     stride >>= FB_SHIFT;
388
389 #if FB_SHIFT < 2
390     if (pixman_multiply_overflows_int (stride, sizeof (uint32_t)))
391         return NULL;
392 #endif
393     stride *= sizeof (uint32_t);
394
395     if (pixman_multiply_overflows_int (height, stride))
396         return NULL;
397
398     buf_size = height * stride;
399
400     if (rowstride_bytes)
401         *rowstride_bytes = stride;
402
403     return calloc (buf_size, 1);
404 }
405
406 static void
407 reset_clip_region (pixman_image_t *image)
408 {
409     pixman_region32_fini (&image->common.clip_region);
410
411     if (image->type == BITS)
412     {
413         pixman_region32_init_rect (&image->common.clip_region, 0, 0,
414                                    image->bits.width, image->bits.height);
415     }
416     else
417     {
418         pixman_region32_init (&image->common.clip_region);
419     }
420 }
421
422 PIXMAN_EXPORT pixman_image_t *
423 pixman_image_create_bits (pixman_format_code_t  format,
424                           int                   width,
425                           int                   height,
426                           uint32_t             *bits,
427                           int                   rowstride_bytes)
428 {
429     pixman_image_t *image;
430     uint32_t *free_me = NULL;
431
432     /* must be a whole number of uint32_t's
433      */
434     return_val_if_fail (bits == NULL ||
435                         (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
436
437     if (!bits && width && height)
438     {
439         free_me = bits = create_bits (format, width, height, &rowstride_bytes);
440         if (!bits)
441             return NULL;
442     }
443
444     image = allocate_image();
445
446     if (!image) {
447         if (free_me)
448             free (free_me);
449         return NULL;
450     }
451     
452     image->type = BITS;
453     image->bits.format = format;
454     image->bits.width = width;
455     image->bits.height = height;
456     image->bits.bits = bits;
457     image->bits.free_me = free_me;
458
459     image->bits.rowstride = rowstride_bytes / (int) sizeof (uint32_t); /* we store it in number
460                                                                   * of uint32_t's
461                                                                   */
462     image->bits.indexed = NULL;
463
464     pixman_region32_fini (&image->common.full_region);
465     pixman_region32_init_rect (&image->common.full_region, 0, 0,
466                                image->bits.width, image->bits.height);
467
468     reset_clip_region (image);
469     return image;
470 }
471
472 PIXMAN_EXPORT pixman_bool_t
473 pixman_image_set_clip_region32 (pixman_image_t *image,
474                                 pixman_region32_t *region)
475 {
476     image_common_t *common = (image_common_t *)image;
477
478     if (region)
479     {
480         return pixman_region32_copy (&common->clip_region, region);
481     }
482     else
483     {
484         reset_clip_region (image);
485
486         return TRUE;
487     }
488 }
489
490
491 PIXMAN_EXPORT pixman_bool_t
492 pixman_image_set_clip_region (pixman_image_t    *image,
493                               pixman_region16_t *region)
494 {
495     image_common_t *common = (image_common_t *)image;
496
497     if (region)
498     {
499         return pixman_region32_copy_from_region16 (&common->clip_region, region);
500     }
501     else
502     {
503         reset_clip_region (image);
504
505         return TRUE;
506     }
507 }
508
509 /* Sets whether the clip region includes a clip region set by the client
510  */
511 PIXMAN_EXPORT void
512 pixman_image_set_has_client_clip (pixman_image_t *image,
513                                   pixman_bool_t   client_clip)
514 {
515     image->common.has_client_clip = client_clip;
516 }
517
518 PIXMAN_EXPORT pixman_bool_t
519 pixman_image_set_transform (pixman_image_t           *image,
520                             const pixman_transform_t *transform)
521 {
522     static const pixman_transform_t id =
523     {
524         { { pixman_fixed_1, 0, 0 },
525           { 0, pixman_fixed_1, 0 },
526           { 0, 0, pixman_fixed_1 }
527         }
528     };
529
530     image_common_t *common = (image_common_t *)image;
531
532     if (common->transform == transform)
533         return TRUE;
534
535     if (memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
536     {
537         free(common->transform);
538         common->transform = NULL;
539         return TRUE;
540     }
541
542     if (common->transform == NULL)
543         common->transform = malloc (sizeof (pixman_transform_t));
544     if (common->transform == NULL)
545         return FALSE;
546
547     memcpy(common->transform, transform, sizeof(pixman_transform_t));
548
549     return TRUE;
550 }
551
552 PIXMAN_EXPORT void
553 pixman_image_set_repeat (pixman_image_t  *image,
554                          pixman_repeat_t  repeat)
555 {
556     image->common.repeat = repeat;
557 }
558
559 PIXMAN_EXPORT pixman_bool_t
560 pixman_image_set_filter (pixman_image_t       *image,
561                          pixman_filter_t       filter,
562                          const pixman_fixed_t *params,
563                          int                   n_params)
564 {
565     image_common_t *common = (image_common_t *)image;
566     pixman_fixed_t *new_params;
567
568     if (params == common->filter_params && filter == common->filter)
569         return TRUE;
570
571     new_params = NULL;
572     if (params)
573     {
574         new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
575         if (!new_params)
576             return FALSE;
577
578         memcpy (new_params,
579                 params, n_params * sizeof (pixman_fixed_t));
580     }
581
582     common->filter = filter;
583
584     if (common->filter_params)
585         free (common->filter_params);
586
587     common->filter_params = new_params;
588     common->n_filter_params = n_params;
589     return TRUE;
590 }
591
592 PIXMAN_EXPORT void
593 pixman_image_set_source_clipping (pixman_image_t  *image,
594                                   pixman_bool_t    source_clipping)
595 {
596     image_common_t *common = &image->common;
597
598     if (source_clipping)
599         common->src_clip = &common->clip_region;
600     else
601         common->src_clip = &common->full_region;
602 }
603
604 /* Unlike all the other property setters, this function does not
605  * copy the content of indexed. Doing this copying is simply
606  * way, way too expensive.
607  */
608 PIXMAN_EXPORT void
609 pixman_image_set_indexed (pixman_image_t         *image,
610                           const pixman_indexed_t *indexed)
611 {
612     bits_image_t *bits = (bits_image_t *)image;
613
614     bits->indexed = indexed;
615 }
616
617 PIXMAN_EXPORT void
618 pixman_image_set_alpha_map (pixman_image_t *image,
619                             pixman_image_t *alpha_map,
620                             int16_t         x,
621                             int16_t         y)
622 {
623     image_common_t *common = (image_common_t *)image;
624
625     return_if_fail (!alpha_map || alpha_map->type == BITS);
626
627     if (common->alpha_map != (bits_image_t *)alpha_map)
628     {
629         if (common->alpha_map)
630             pixman_image_unref ((pixman_image_t *)common->alpha_map);
631
632         if (alpha_map)
633             common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
634         else
635             common->alpha_map = NULL;
636     }
637
638     common->alpha_origin.x = x;
639     common->alpha_origin.y = y;
640 }
641
642 PIXMAN_EXPORT void
643 pixman_image_set_component_alpha   (pixman_image_t       *image,
644                                     pixman_bool_t         component_alpha)
645 {
646     image->common.component_alpha = component_alpha;
647 }
648
649
650 PIXMAN_EXPORT void
651 pixman_image_set_accessors (pixman_image_t             *image,
652                             pixman_read_memory_func_t   read_func,
653                             pixman_write_memory_func_t  write_func)
654 {
655     return_if_fail (image != NULL);
656
657     image->common.read_func = read_func;
658     image->common.write_func = write_func;
659 }
660
661 PIXMAN_EXPORT uint32_t *
662 pixman_image_get_data (pixman_image_t *image)
663 {
664     if (image->type == BITS)
665         return image->bits.bits;
666
667     return NULL;
668 }
669
670 PIXMAN_EXPORT int
671 pixman_image_get_width (pixman_image_t *image)
672 {
673     if (image->type == BITS)
674         return image->bits.width;
675
676     return 0;
677 }
678
679 PIXMAN_EXPORT int
680 pixman_image_get_height (pixman_image_t *image)
681 {
682     if (image->type == BITS)
683         return image->bits.height;
684
685     return 0;
686 }
687
688 PIXMAN_EXPORT int
689 pixman_image_get_stride (pixman_image_t *image)
690 {
691     if (image->type == BITS)
692         return image->bits.rowstride * (int) sizeof (uint32_t);
693
694     return 0;
695 }
696
697 PIXMAN_EXPORT int
698 pixman_image_get_depth (pixman_image_t *image)
699 {
700     if (image->type == BITS)
701         return PIXMAN_FORMAT_DEPTH (image->bits.format);
702
703     return 0;
704 }
705
706 static pixman_bool_t
707 color_to_pixel (pixman_color_t *color,
708                 uint32_t       *pixel,
709                 pixman_format_code_t format)
710 {
711     uint32_t c = color_to_uint32 (color);
712
713     if (!(format == PIXMAN_a8r8g8b8     ||
714           format == PIXMAN_x8r8g8b8     ||
715           format == PIXMAN_a8b8g8r8     ||
716           format == PIXMAN_x8b8g8r8     ||
717           format == PIXMAN_b8g8r8a8     ||
718           format == PIXMAN_b8g8r8x8     ||
719           format == PIXMAN_r5g6b5       ||
720           format == PIXMAN_b5g6r5       ||
721           format == PIXMAN_a8))
722     {
723         return FALSE;
724     }
725
726     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
727     {
728         c = ((c & 0xff000000) >>  0) |
729             ((c & 0x00ff0000) >> 16) |
730             ((c & 0x0000ff00) >>  0) |
731             ((c & 0x000000ff) << 16);
732     }
733     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
734     {
735         c = ((c & 0xff000000) >> 24) |
736             ((c & 0x00ff0000) >>  8) |
737             ((c & 0x0000ff00) <<  8) |
738             ((c & 0x000000ff) << 24);
739     }
740
741     if (format == PIXMAN_a8)
742         c = c >> 24;
743     else if (format == PIXMAN_r5g6b5 ||
744              format == PIXMAN_b5g6r5)
745         c = cvt8888to0565 (c);
746
747 #if 0
748     printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
749     printf ("pixel: %x\n", c);
750 #endif
751
752     *pixel = c;
753     return TRUE;
754 }
755
756 PIXMAN_EXPORT pixman_bool_t
757 pixman_image_fill_rectangles (pixman_op_t                   op,
758                               pixman_image_t               *dest,
759                               pixman_color_t               *color,
760                               int                           n_rects,
761                               const pixman_rectangle16_t   *rects)
762 {
763     pixman_image_t *solid;
764     pixman_color_t c;
765     int i;
766
767     if (color->alpha == 0xffff)
768     {
769         if (op == PIXMAN_OP_OVER)
770             op = PIXMAN_OP_SRC;
771     }
772
773     if (op == PIXMAN_OP_CLEAR)
774     {
775         c.red = 0;
776         c.green = 0;
777         c.blue = 0;
778         c.alpha = 0;
779
780         color = &c;
781
782         op = PIXMAN_OP_SRC;
783     }
784
785     if (op == PIXMAN_OP_SRC)
786     {
787         uint32_t pixel;
788
789         if (color_to_pixel (color, &pixel, dest->bits.format))
790         {
791             for (i = 0; i < n_rects; ++i)
792             {
793                 pixman_region32_t fill_region;
794                 int n_boxes, j;
795                 pixman_box32_t *boxes;
796
797                 pixman_region32_init_rect (&fill_region, rects[i].x, rects[i].y, rects[i].width, rects[i].height);
798                 if (!pixman_region32_intersect (&fill_region,
799                                                 &fill_region,
800                                                 &dest->common.clip_region))
801                     return FALSE;
802
803
804                 boxes = pixman_region32_rectangles (&fill_region, &n_boxes);
805                 for (j = 0; j < n_boxes; ++j)
806                 {
807                     const pixman_box32_t *box = &(boxes[j]);
808                     pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
809                                  box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1,
810                                  pixel);
811                 }
812
813                 pixman_region32_fini (&fill_region);
814             }
815             return TRUE;
816         }
817     }
818
819     solid = pixman_image_create_solid_fill (color);
820     if (!solid)
821         return FALSE;
822
823     for (i = 0; i < n_rects; ++i)
824     {
825         const pixman_rectangle16_t *rect = &(rects[i]);
826
827         pixman_image_composite (op, solid, NULL, dest,
828                                 0, 0, 0, 0,
829                                 rect->x, rect->y,
830                                 rect->width, rect->height);
831     }
832
833     pixman_image_unref (solid);
834
835     return TRUE;
836 }
837
838 pixman_bool_t
839 pixman_image_can_get_solid (pixman_image_t *image)
840 {
841     if (image->type == SOLID)
842         return TRUE;
843
844     if (image->type != BITS     ||
845         image->bits.width != 1  ||
846         image->bits.height != 1)
847     {
848         return FALSE;
849     }
850
851     if (image->common.repeat != PIXMAN_REPEAT_NORMAL)
852         return FALSE;
853
854     switch (image->bits.format)
855     {
856     case PIXMAN_a8r8g8b8:
857     case PIXMAN_x8r8g8b8:
858     case PIXMAN_a8b8g8r8:
859     case PIXMAN_x8b8g8r8:
860     case PIXMAN_b8g8r8a8:
861     case PIXMAN_b8g8r8x8:
862     case PIXMAN_r8g8b8:
863     case PIXMAN_b8g8r8:
864     case PIXMAN_r5g6b5:
865     case PIXMAN_b5g6r5:
866         return TRUE;
867     default:
868         return FALSE;
869     }
870 }
871
872 pixman_bool_t
873 pixman_image_is_opaque(pixman_image_t *image)
874 {
875     int i = 0;
876     int gradientNumberOfColors = 0;
877
878     if(image->common.alpha_map)
879         return FALSE;
880
881     switch(image->type)
882     {
883     case BITS:
884         if(PIXMAN_FORMAT_A(image->bits.format))
885             return FALSE;
886         break;
887
888     case LINEAR:
889     case CONICAL:
890     case RADIAL:
891         gradientNumberOfColors = image->gradient.n_stops;
892         i=0;
893         while(i<gradientNumberOfColors)
894         {
895             if(image->gradient.stops[i].color.alpha != 0xffff)
896                 return FALSE;
897             i++;
898         }
899         break;
900
901     case SOLID:
902          if(Alpha(image->solid.color) != 0xff)
903             return FALSE;
904         break;
905     }
906
907     /* Convolution filters can introduce translucency if the sum of the weights
908        is lower than 1. */
909     if (image->common.filter == PIXMAN_FILTER_CONVOLUTION)
910          return FALSE;
911
912     if (image->common.repeat == PIXMAN_REPEAT_NONE)
913     {
914         if (image->common.filter != PIXMAN_FILTER_NEAREST)
915             return FALSE;
916
917         if (image->common.transform)
918             return FALSE;
919
920         /* Gradients do not necessarily cover the entire compositing area */
921         if (image->type == LINEAR || image->type == CONICAL || image->type == RADIAL)
922             return FALSE;
923     }
924
925      return TRUE;
926 }