Fix pixman_image_is_opaque()
[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 #include <assert.h>
31
32 #include "pixman-private.h"
33
34 #define Alpha(x) ((x) >> 24)
35
36 pixman_bool_t
37 _pixman_init_gradient (gradient_t     *gradient,
38                        const pixman_gradient_stop_t *stops,
39                        int             n_stops)
40 {
41     return_val_if_fail (n_stops > 0, FALSE);
42
43     gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t));
44     if (!gradient->stops)
45         return FALSE;
46
47     memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
48
49     gradient->n_stops = n_stops;
50
51     gradient->stop_range = 0xffff;
52     gradient->color_table = NULL;
53     gradient->color_table_size = 0;
54     gradient->common.class = SOURCE_IMAGE_CLASS_UNKNOWN;
55
56     return TRUE;
57 }
58
59 /*
60  * By default, just evaluate the image at 32bpp and expand.  Individual image
61  * types can plug in a better scanline getter if they want to. For example
62  * we  could produce smoother gradients by evaluating them at higher color depth, but
63  * that's a project for the future.
64  */
65 void
66 _pixman_image_get_scanline_64_generic (pixman_image_t * pict, int x, int y, int width,
67                                        uint64_t *buffer, uint64_t *mask, uint32_t maskBits)
68 {
69     uint32_t *mask8 = NULL;
70
71     // Contract the mask image, if one exists, so that the 32-bit fetch function
72     // can use it.
73     if (mask) {
74         mask8 = pixman_malloc_ab(width, sizeof(uint32_t));
75         if (!mask8)
76             return;
77         
78         pixman_contract(mask8, mask, width);
79     }
80
81     // Fetch the source image into the first half of buffer.
82     _pixman_image_get_scanline_32 (pict, x, y, width, (uint32_t*)buffer, mask8,
83                                    maskBits);
84
85     // Expand from 32bpp to 64bpp in place.
86     pixman_expand(buffer, (uint32_t*)buffer, PIXMAN_a8r8g8b8, width);
87
88     free(mask8);
89 }
90
91 pixman_image_t *
92 _pixman_image_allocate (void)
93 {
94     pixman_image_t *image = malloc (sizeof (pixman_image_t));
95
96     if (image)
97     {
98         image_common_t *common = &image->common;
99
100         pixman_region32_init (&common->full_region);
101         pixman_region32_init (&common->clip_region);
102         common->src_clip = &common->full_region;
103         common->has_client_clip = FALSE;
104         common->transform = NULL;
105         common->repeat = PIXMAN_REPEAT_NONE;
106         common->filter = PIXMAN_FILTER_NEAREST;
107         common->filter_params = NULL;
108         common->n_filter_params = 0;
109         common->alpha_map = NULL;
110         common->component_alpha = FALSE;
111         common->ref_count = 1;
112         common->read_func = NULL;
113         common->write_func = NULL;
114         common->classify = NULL;
115     }
116
117     return image;
118 }
119
120 source_pict_class_t
121 _pixman_image_classify (pixman_image_t *image,
122                         int             x,
123                         int             y,
124                         int             width,
125                         int             height)
126 {
127     if (image->common.classify)
128         return image->common.classify (image, x, y, width, height);
129     else
130         return SOURCE_IMAGE_CLASS_UNKNOWN;
131 }
132
133 void
134 _pixman_image_get_scanline_32 (pixman_image_t *image, int x, int y, int width,
135                                uint32_t *buffer, uint32_t *mask, uint32_t mask_bits)
136 {
137     image->common.get_scanline_32 (image, x, y, width, buffer, mask, mask_bits);
138 }
139
140 void
141 _pixman_image_get_scanline_64 (pixman_image_t *image, int x, int y, int width,
142                                uint32_t *buffer, uint32_t *unused, uint32_t unused2)
143 {
144     image->common.get_scanline_64 (image, x, y, width, buffer, unused, unused2);
145 }
146
147 /* Even thought the type of buffer is uint32_t *, the function actually expects
148  * a uint64_t *buffer.
149  */
150
151 scanFetchProc
152 _pixman_image_get_fetcher (pixman_image_t *image,
153                            int             wide)
154 {
155     assert (image->common.get_scanline_64);
156     assert (image->common.get_scanline_32);
157     
158     if (wide)
159         return image->common.get_scanline_64;
160     else
161         return image->common.get_scanline_32;
162 }
163
164 #define WRITE_ACCESS(f) ((image->common.write_func)? f##_accessors : f)
165
166 static void
167 image_property_changed (pixman_image_t *image)
168 {
169     
170     
171     image->common.property_changed (image);
172 }
173
174 /* Ref Counting */
175 PIXMAN_EXPORT pixman_image_t *
176 pixman_image_ref (pixman_image_t *image)
177 {
178     image->common.ref_count++;
179
180     return image;
181 }
182
183 /* returns TRUE when the image is freed */
184 PIXMAN_EXPORT pixman_bool_t
185 pixman_image_unref (pixman_image_t *image)
186 {
187     image_common_t *common = (image_common_t *)image;
188
189     common->ref_count--;
190
191     if (common->ref_count == 0)
192     {
193         pixman_region32_fini (&common->clip_region);
194         pixman_region32_fini (&common->full_region);
195
196         if (common->transform)
197             free (common->transform);
198
199         if (common->filter_params)
200             free (common->filter_params);
201
202         if (common->alpha_map)
203             pixman_image_unref ((pixman_image_t *)common->alpha_map);
204
205 #if 0
206         if (image->type == BITS && image->bits.indexed)
207             free (image->bits.indexed);
208 #endif
209
210 #if 0
211         memset (image, 0xaa, sizeof (pixman_image_t));
212 #endif
213         if (image->type == LINEAR || image->type == RADIAL || image->type == CONICAL)
214         {
215             if (image->gradient.stops)
216                 free (image->gradient.stops);
217         }
218
219
220         if (image->type == BITS && image->bits.free_me)
221             free (image->bits.free_me);
222
223         free (image);
224
225         return TRUE;
226     }
227
228     return FALSE;
229 }
230
231 /* Constructors */
232
233 void
234 _pixman_image_reset_clip_region (pixman_image_t *image)
235 {
236     pixman_region32_fini (&image->common.clip_region);
237
238     if (image->type == BITS)
239     {
240         pixman_region32_init_rect (&image->common.clip_region, 0, 0,
241                                    image->bits.width, image->bits.height);
242     }
243     else
244     {
245         pixman_region32_init (&image->common.clip_region);
246     }
247 }
248
249 PIXMAN_EXPORT pixman_bool_t
250 pixman_image_set_clip_region32 (pixman_image_t *image,
251                                 pixman_region32_t *region)
252 {
253     image_common_t *common = (image_common_t *)image;
254     pixman_bool_t result;
255
256     if (region)
257     {
258         result = pixman_region32_copy (&common->clip_region, region);
259     }
260     else
261     {
262         _pixman_image_reset_clip_region (image);
263
264         result = TRUE;
265     }
266
267     image_property_changed (image);
268
269     return result;
270 }
271
272
273 PIXMAN_EXPORT pixman_bool_t
274 pixman_image_set_clip_region (pixman_image_t    *image,
275                               pixman_region16_t *region)
276 {
277     image_common_t *common = (image_common_t *)image;
278     pixman_bool_t result;
279
280     if (region)
281     {
282         result = pixman_region32_copy_from_region16 (&common->clip_region, region);
283     }
284     else
285     {
286         _pixman_image_reset_clip_region (image);
287
288         result = TRUE;
289     }
290
291     image_property_changed (image);
292
293     return result;
294 }
295
296 /* Sets whether the clip region includes a clip region set by the client
297  */
298 PIXMAN_EXPORT void
299 pixman_image_set_has_client_clip (pixman_image_t *image,
300                                   pixman_bool_t   client_clip)
301 {
302     image->common.has_client_clip = client_clip;
303
304     image_property_changed (image);
305 }
306
307 PIXMAN_EXPORT pixman_bool_t
308 pixman_image_set_transform (pixman_image_t           *image,
309                             const pixman_transform_t *transform)
310 {
311     static const pixman_transform_t id =
312     {
313         { { pixman_fixed_1, 0, 0 },
314           { 0, pixman_fixed_1, 0 },
315           { 0, 0, pixman_fixed_1 }
316         }
317     };
318
319     image_common_t *common = (image_common_t *)image;
320     pixman_bool_t result;
321
322     if (common->transform == transform)
323         return TRUE;
324
325     if (memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
326     {
327         free(common->transform);
328         common->transform = NULL;
329         result = TRUE;
330         goto out;
331     }
332
333     if (common->transform == NULL)
334         common->transform = malloc (sizeof (pixman_transform_t));
335
336     if (common->transform == NULL)
337     {
338         result = FALSE;
339         goto out;
340     }
341
342     memcpy(common->transform, transform, sizeof(pixman_transform_t));
343
344 out:
345     image_property_changed (image);
346     
347     return TRUE;
348 }
349
350 PIXMAN_EXPORT void
351 pixman_image_set_repeat (pixman_image_t  *image,
352                          pixman_repeat_t  repeat)
353 {
354     image->common.repeat = repeat;
355
356     image_property_changed (image);
357 }
358
359 PIXMAN_EXPORT pixman_bool_t
360 pixman_image_set_filter (pixman_image_t       *image,
361                          pixman_filter_t       filter,
362                          const pixman_fixed_t *params,
363                          int                   n_params)
364 {
365     image_common_t *common = (image_common_t *)image;
366     pixman_fixed_t *new_params;
367
368     if (params == common->filter_params && filter == common->filter)
369         return TRUE;
370
371     new_params = NULL;
372     if (params)
373     {
374         new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
375         if (!new_params)
376             return FALSE;
377
378         memcpy (new_params,
379                 params, n_params * sizeof (pixman_fixed_t));
380     }
381
382     common->filter = filter;
383
384     if (common->filter_params)
385         free (common->filter_params);
386
387     common->filter_params = new_params;
388     common->n_filter_params = n_params;
389
390     image_property_changed (image);
391     return TRUE;
392 }
393
394 PIXMAN_EXPORT void
395 pixman_image_set_source_clipping (pixman_image_t  *image,
396                                   pixman_bool_t    source_clipping)
397 {
398     image_common_t *common = &image->common;
399
400     if (source_clipping)
401         common->src_clip = &common->clip_region;
402     else
403         common->src_clip = &common->full_region;
404
405     image_property_changed (image);
406 }
407
408 /* Unlike all the other property setters, this function does not
409  * copy the content of indexed. Doing this copying is simply
410  * way, way too expensive.
411  */
412 PIXMAN_EXPORT void
413 pixman_image_set_indexed (pixman_image_t         *image,
414                           const pixman_indexed_t *indexed)
415 {
416     bits_image_t *bits = (bits_image_t *)image;
417
418     bits->indexed = indexed;
419
420     image_property_changed (image);
421 }
422
423 PIXMAN_EXPORT void
424 pixman_image_set_alpha_map (pixman_image_t *image,
425                             pixman_image_t *alpha_map,
426                             int16_t         x,
427                             int16_t         y)
428 {
429     image_common_t *common = (image_common_t *)image;
430
431     return_if_fail (!alpha_map || alpha_map->type == BITS);
432
433     if (common->alpha_map != (bits_image_t *)alpha_map)
434     {
435         if (common->alpha_map)
436             pixman_image_unref ((pixman_image_t *)common->alpha_map);
437
438         if (alpha_map)
439             common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
440         else
441             common->alpha_map = NULL;
442     }
443
444     common->alpha_origin.x = x;
445     common->alpha_origin.y = y;
446
447     image_property_changed (image);
448 }
449
450 PIXMAN_EXPORT void
451 pixman_image_set_component_alpha   (pixman_image_t       *image,
452                                     pixman_bool_t         component_alpha)
453 {
454     image->common.component_alpha = component_alpha;
455
456     image_property_changed (image);
457 }
458
459
460 PIXMAN_EXPORT void
461 pixman_image_set_accessors (pixman_image_t             *image,
462                             pixman_read_memory_func_t   read_func,
463                             pixman_write_memory_func_t  write_func)
464 {
465     return_if_fail (image != NULL);
466
467     image->common.read_func = read_func;
468     image->common.write_func = write_func;
469
470     image_property_changed (image);
471 }
472
473 PIXMAN_EXPORT uint32_t *
474 pixman_image_get_data (pixman_image_t *image)
475 {
476     if (image->type == BITS)
477         return image->bits.bits;
478
479     return NULL;
480 }
481
482 PIXMAN_EXPORT int
483 pixman_image_get_width (pixman_image_t *image)
484 {
485     if (image->type == BITS)
486         return image->bits.width;
487
488     return 0;
489 }
490
491 PIXMAN_EXPORT int
492 pixman_image_get_height (pixman_image_t *image)
493 {
494     if (image->type == BITS)
495         return image->bits.height;
496
497     return 0;
498 }
499
500 PIXMAN_EXPORT int
501 pixman_image_get_stride (pixman_image_t *image)
502 {
503     if (image->type == BITS)
504         return image->bits.rowstride * (int) sizeof (uint32_t);
505
506     return 0;
507 }
508
509 PIXMAN_EXPORT int
510 pixman_image_get_depth (pixman_image_t *image)
511 {
512     if (image->type == BITS)
513         return PIXMAN_FORMAT_DEPTH (image->bits.format);
514
515     return 0;
516 }
517
518 static uint32_t
519 color_to_uint32 (const pixman_color_t *color)
520 {
521     return
522         (color->alpha >> 8 << 24) |
523         (color->red >> 8 << 16) |
524         (color->green & 0xff00) |
525         (color->blue >> 8);
526 }
527
528 static pixman_bool_t
529 color_to_pixel (pixman_color_t *color,
530                 uint32_t       *pixel,
531                 pixman_format_code_t format)
532 {
533     uint32_t c = color_to_uint32 (color);
534
535     if (!(format == PIXMAN_a8r8g8b8     ||
536           format == PIXMAN_x8r8g8b8     ||
537           format == PIXMAN_a8b8g8r8     ||
538           format == PIXMAN_x8b8g8r8     ||
539           format == PIXMAN_b8g8r8a8     ||
540           format == PIXMAN_b8g8r8x8     ||
541           format == PIXMAN_r5g6b5       ||
542           format == PIXMAN_b5g6r5       ||
543           format == PIXMAN_a8))
544     {
545         return FALSE;
546     }
547
548     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
549     {
550         c = ((c & 0xff000000) >>  0) |
551             ((c & 0x00ff0000) >> 16) |
552             ((c & 0x0000ff00) >>  0) |
553             ((c & 0x000000ff) << 16);
554     }
555     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
556     {
557         c = ((c & 0xff000000) >> 24) |
558             ((c & 0x00ff0000) >>  8) |
559             ((c & 0x0000ff00) <<  8) |
560             ((c & 0x000000ff) << 24);
561     }
562
563     if (format == PIXMAN_a8)
564         c = c >> 24;
565     else if (format == PIXMAN_r5g6b5 ||
566              format == PIXMAN_b5g6r5)
567         c = cvt8888to0565 (c);
568
569 #if 0
570     printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
571     printf ("pixel: %x\n", c);
572 #endif
573
574     *pixel = c;
575     return TRUE;
576 }
577
578 PIXMAN_EXPORT pixman_bool_t
579 pixman_image_fill_rectangles (pixman_op_t                   op,
580                               pixman_image_t               *dest,
581                               pixman_color_t               *color,
582                               int                           n_rects,
583                               const pixman_rectangle16_t   *rects)
584 {
585     pixman_image_t *solid;
586     pixman_color_t c;
587     int i;
588
589     if (color->alpha == 0xffff)
590     {
591         if (op == PIXMAN_OP_OVER)
592             op = PIXMAN_OP_SRC;
593     }
594
595     if (op == PIXMAN_OP_CLEAR)
596     {
597         c.red = 0;
598         c.green = 0;
599         c.blue = 0;
600         c.alpha = 0;
601
602         color = &c;
603
604         op = PIXMAN_OP_SRC;
605     }
606
607     if (op == PIXMAN_OP_SRC)
608     {
609         uint32_t pixel;
610
611         if (color_to_pixel (color, &pixel, dest->bits.format))
612         {
613             for (i = 0; i < n_rects; ++i)
614             {
615                 pixman_region32_t fill_region;
616                 int n_boxes, j;
617                 pixman_box32_t *boxes;
618
619                 pixman_region32_init_rect (&fill_region, rects[i].x, rects[i].y, rects[i].width, rects[i].height);
620                 if (!pixman_region32_intersect (&fill_region,
621                                                 &fill_region,
622                                                 &dest->common.clip_region))
623                     return FALSE;
624
625
626                 boxes = pixman_region32_rectangles (&fill_region, &n_boxes);
627                 for (j = 0; j < n_boxes; ++j)
628                 {
629                     const pixman_box32_t *box = &(boxes[j]);
630                     pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
631                                  box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1,
632                                  pixel);
633                 }
634
635                 pixman_region32_fini (&fill_region);
636             }
637             return TRUE;
638         }
639     }
640
641     solid = pixman_image_create_solid_fill (color);
642     if (!solid)
643         return FALSE;
644
645     for (i = 0; i < n_rects; ++i)
646     {
647         const pixman_rectangle16_t *rect = &(rects[i]);
648
649         pixman_image_composite (op, solid, NULL, dest,
650                                 0, 0, 0, 0,
651                                 rect->x, rect->y,
652                                 rect->width, rect->height);
653     }
654
655     pixman_image_unref (solid);
656
657     return TRUE;
658 }
659
660 pixman_bool_t
661 pixman_image_can_get_solid (pixman_image_t *image)
662 {
663     if (image->type == SOLID)
664         return TRUE;
665
666     if (image->type != BITS     ||
667         image->bits.width != 1  ||
668         image->bits.height != 1)
669     {
670         return FALSE;
671     }
672
673     if (image->common.repeat != PIXMAN_REPEAT_NORMAL)
674         return FALSE;
675
676     switch (image->bits.format)
677     {
678     case PIXMAN_a8r8g8b8:
679     case PIXMAN_x8r8g8b8:
680     case PIXMAN_a8b8g8r8:
681     case PIXMAN_x8b8g8r8:
682     case PIXMAN_b8g8r8a8:
683     case PIXMAN_b8g8r8x8:
684     case PIXMAN_r8g8b8:
685     case PIXMAN_b8g8r8:
686     case PIXMAN_r5g6b5:
687     case PIXMAN_b5g6r5:
688         return TRUE;
689     default:
690         return FALSE;
691     }
692 }
693
694 pixman_bool_t
695 pixman_image_is_opaque (pixman_image_t *image)
696 {
697     int i;
698
699     if (image->common.alpha_map)
700         return FALSE;
701
702     switch (image->type)
703     {
704     case BITS:
705         if (image->common.repeat == PIXMAN_REPEAT_NONE)
706             return FALSE;
707         
708         if (PIXMAN_FORMAT_A (image->bits.format))
709             return FALSE;
710         break;
711
712     case LINEAR:
713     case RADIAL:
714         if (image->common.repeat == PIXMAN_REPEAT_NONE)
715             return FALSE;
716         
717         for (i = 0; i < image->gradient.n_stops; ++i)
718         {
719             if (image->gradient.stops[i].color.alpha != 0xffff)
720                 return FALSE;
721         }
722         break;
723
724     case CONICAL:
725         /* Conical gradients always have a transparent border */
726         return FALSE;
727         break;
728         
729     case SOLID:
730          if (Alpha (image->solid.color) != 0xff)
731             return FALSE;
732         break;
733     }
734
735     /* Convolution filters can introduce translucency if the sum of the
736      * weights is lower than 1.
737      */
738     if (image->common.filter == PIXMAN_FILTER_CONVOLUTION)
739          return FALSE;
740
741      return TRUE;
742 }