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