Simplify clipping rule
[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->clip_region);
101
102         common->have_clip_region = FALSE;
103         common->clip_sources = 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         common->client_clip = FALSE;
116     }
117
118     return image;
119 }
120
121 source_pict_class_t
122 _pixman_image_classify (pixman_image_t *image,
123                         int             x,
124                         int             y,
125                         int             width,
126                         int             height)
127 {
128     if (image->common.classify)
129         return image->common.classify (image, x, y, width, height);
130     else
131         return SOURCE_IMAGE_CLASS_UNKNOWN;
132 }
133
134 void
135 _pixman_image_get_scanline_32 (pixman_image_t *image, int x, int y, int width,
136                                uint32_t *buffer, uint32_t *mask, uint32_t mask_bits)
137 {
138     image->common.get_scanline_32 (image, x, y, width, buffer, mask, mask_bits);
139 }
140
141 void
142 _pixman_image_get_scanline_64 (pixman_image_t *image, int x, int y, int width,
143                                uint32_t *buffer, uint32_t *unused, uint32_t unused2)
144 {
145     image->common.get_scanline_64 (image, x, y, width, buffer, unused, unused2);
146 }
147
148 /* Even thought the type of buffer is uint32_t *, the function actually expects
149  * a uint64_t *buffer.
150  */
151
152 scanFetchProc
153 _pixman_image_get_fetcher (pixman_image_t *image,
154                            int             wide)
155 {
156     assert (image->common.get_scanline_64);
157     assert (image->common.get_scanline_32);
158     
159     if (wide)
160         return image->common.get_scanline_64;
161     else
162         return image->common.get_scanline_32;
163 }
164
165 #define WRITE_ACCESS(f) ((image->common.write_func)? f##_accessors : f)
166
167 static void
168 image_property_changed (pixman_image_t *image)
169 {
170     
171     
172     image->common.property_changed (image);
173 }
174
175 /* Ref Counting */
176 PIXMAN_EXPORT pixman_image_t *
177 pixman_image_ref (pixman_image_t *image)
178 {
179     image->common.ref_count++;
180
181     return image;
182 }
183
184 /* returns TRUE when the image is freed */
185 PIXMAN_EXPORT pixman_bool_t
186 pixman_image_unref (pixman_image_t *image)
187 {
188     image_common_t *common = (image_common_t *)image;
189
190     common->ref_count--;
191
192     if (common->ref_count == 0)
193     {
194         pixman_region32_fini (&common->clip_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     image->common.have_clip_region = FALSE;
237 }
238
239 PIXMAN_EXPORT pixman_bool_t
240 pixman_image_set_clip_region32 (pixman_image_t *image,
241                                 pixman_region32_t *region)
242 {
243     image_common_t *common = (image_common_t *)image;
244     pixman_bool_t result;
245
246     if (region)
247     {
248         if ((result = pixman_region32_copy (&common->clip_region, region)))
249             image->common.have_clip_region = TRUE;
250     }
251     else
252     {
253         _pixman_image_reset_clip_region (image);
254
255         result = TRUE;
256     }
257
258     image_property_changed (image);
259
260     return result;
261 }
262
263
264 PIXMAN_EXPORT pixman_bool_t
265 pixman_image_set_clip_region (pixman_image_t    *image,
266                               pixman_region16_t *region)
267 {
268     image_common_t *common = (image_common_t *)image;
269     pixman_bool_t result;
270
271     if (region)
272     {
273         if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
274             image->common.have_clip_region = TRUE;
275     }
276     else
277     {
278         _pixman_image_reset_clip_region (image);
279
280         result = TRUE;
281     }
282
283     image_property_changed (image);
284
285     return result;
286 }
287
288 PIXMAN_EXPORT void
289 pixman_image_set_has_client_clip (pixman_image_t *image,
290                                   pixman_bool_t   client_clip)
291 {
292     image->common.client_clip = client_clip;
293 }
294
295 PIXMAN_EXPORT pixman_bool_t
296 pixman_image_set_transform (pixman_image_t           *image,
297                             const pixman_transform_t *transform)
298 {
299     static const pixman_transform_t id =
300     {
301         { { pixman_fixed_1, 0, 0 },
302           { 0, pixman_fixed_1, 0 },
303           { 0, 0, pixman_fixed_1 }
304         }
305     };
306
307     image_common_t *common = (image_common_t *)image;
308     pixman_bool_t result;
309
310     if (common->transform == transform)
311         return TRUE;
312
313     if (memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
314     {
315         free(common->transform);
316         common->transform = NULL;
317         result = TRUE;
318         goto out;
319     }
320
321     if (common->transform == NULL)
322         common->transform = malloc (sizeof (pixman_transform_t));
323
324     if (common->transform == NULL)
325     {
326         result = FALSE;
327         goto out;
328     }
329
330     memcpy(common->transform, transform, sizeof(pixman_transform_t));
331
332 out:
333     image_property_changed (image);
334     
335     return TRUE;
336 }
337
338 PIXMAN_EXPORT void
339 pixman_image_set_repeat (pixman_image_t  *image,
340                          pixman_repeat_t  repeat)
341 {
342     image->common.repeat = repeat;
343
344     image_property_changed (image);
345 }
346
347 PIXMAN_EXPORT pixman_bool_t
348 pixman_image_set_filter (pixman_image_t       *image,
349                          pixman_filter_t       filter,
350                          const pixman_fixed_t *params,
351                          int                   n_params)
352 {
353     image_common_t *common = (image_common_t *)image;
354     pixman_fixed_t *new_params;
355
356     if (params == common->filter_params && filter == common->filter)
357         return TRUE;
358
359     new_params = NULL;
360     if (params)
361     {
362         new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
363         if (!new_params)
364             return FALSE;
365
366         memcpy (new_params,
367                 params, n_params * sizeof (pixman_fixed_t));
368     }
369
370     common->filter = filter;
371
372     if (common->filter_params)
373         free (common->filter_params);
374
375     common->filter_params = new_params;
376     common->n_filter_params = n_params;
377
378     image_property_changed (image);
379     return TRUE;
380 }
381
382 PIXMAN_EXPORT void
383 pixman_image_set_source_clipping (pixman_image_t  *image,
384                                   pixman_bool_t    clip_sources)
385 {
386     image->common.clip_sources = clip_sources;
387 }
388
389 /* Unlike all the other property setters, this function does not
390  * copy the content of indexed. Doing this copying is simply
391  * way, way too expensive.
392  */
393 PIXMAN_EXPORT void
394 pixman_image_set_indexed (pixman_image_t         *image,
395                           const pixman_indexed_t *indexed)
396 {
397     bits_image_t *bits = (bits_image_t *)image;
398
399     bits->indexed = indexed;
400
401     image_property_changed (image);
402 }
403
404 PIXMAN_EXPORT void
405 pixman_image_set_alpha_map (pixman_image_t *image,
406                             pixman_image_t *alpha_map,
407                             int16_t         x,
408                             int16_t         y)
409 {
410     image_common_t *common = (image_common_t *)image;
411
412     return_if_fail (!alpha_map || alpha_map->type == BITS);
413
414     if (common->alpha_map != (bits_image_t *)alpha_map)
415     {
416         if (common->alpha_map)
417             pixman_image_unref ((pixman_image_t *)common->alpha_map);
418
419         if (alpha_map)
420             common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
421         else
422             common->alpha_map = NULL;
423     }
424
425     common->alpha_origin.x = x;
426     common->alpha_origin.y = y;
427
428     image_property_changed (image);
429 }
430
431 PIXMAN_EXPORT void
432 pixman_image_set_component_alpha   (pixman_image_t       *image,
433                                     pixman_bool_t         component_alpha)
434 {
435     image->common.component_alpha = component_alpha;
436
437     image_property_changed (image);
438 }
439
440
441 PIXMAN_EXPORT void
442 pixman_image_set_accessors (pixman_image_t             *image,
443                             pixman_read_memory_func_t   read_func,
444                             pixman_write_memory_func_t  write_func)
445 {
446     return_if_fail (image != NULL);
447
448     image->common.read_func = read_func;
449     image->common.write_func = write_func;
450
451     image_property_changed (image);
452 }
453
454 PIXMAN_EXPORT uint32_t *
455 pixman_image_get_data (pixman_image_t *image)
456 {
457     if (image->type == BITS)
458         return image->bits.bits;
459
460     return NULL;
461 }
462
463 PIXMAN_EXPORT int
464 pixman_image_get_width (pixman_image_t *image)
465 {
466     if (image->type == BITS)
467         return image->bits.width;
468
469     return 0;
470 }
471
472 PIXMAN_EXPORT int
473 pixman_image_get_height (pixman_image_t *image)
474 {
475     if (image->type == BITS)
476         return image->bits.height;
477
478     return 0;
479 }
480
481 PIXMAN_EXPORT int
482 pixman_image_get_stride (pixman_image_t *image)
483 {
484     if (image->type == BITS)
485         return image->bits.rowstride * (int) sizeof (uint32_t);
486
487     return 0;
488 }
489
490 PIXMAN_EXPORT int
491 pixman_image_get_depth (pixman_image_t *image)
492 {
493     if (image->type == BITS)
494         return PIXMAN_FORMAT_DEPTH (image->bits.format);
495
496     return 0;
497 }
498
499 static uint32_t
500 color_to_uint32 (const pixman_color_t *color)
501 {
502     return
503         (color->alpha >> 8 << 24) |
504         (color->red >> 8 << 16) |
505         (color->green & 0xff00) |
506         (color->blue >> 8);
507 }
508
509 static pixman_bool_t
510 color_to_pixel (pixman_color_t *color,
511                 uint32_t       *pixel,
512                 pixman_format_code_t format)
513 {
514     uint32_t c = color_to_uint32 (color);
515
516     if (!(format == PIXMAN_a8r8g8b8     ||
517           format == PIXMAN_x8r8g8b8     ||
518           format == PIXMAN_a8b8g8r8     ||
519           format == PIXMAN_x8b8g8r8     ||
520           format == PIXMAN_b8g8r8a8     ||
521           format == PIXMAN_b8g8r8x8     ||
522           format == PIXMAN_r5g6b5       ||
523           format == PIXMAN_b5g6r5       ||
524           format == PIXMAN_a8))
525     {
526         return FALSE;
527     }
528
529     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
530     {
531         c = ((c & 0xff000000) >>  0) |
532             ((c & 0x00ff0000) >> 16) |
533             ((c & 0x0000ff00) >>  0) |
534             ((c & 0x000000ff) << 16);
535     }
536     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
537     {
538         c = ((c & 0xff000000) >> 24) |
539             ((c & 0x00ff0000) >>  8) |
540             ((c & 0x0000ff00) <<  8) |
541             ((c & 0x000000ff) << 24);
542     }
543
544     if (format == PIXMAN_a8)
545         c = c >> 24;
546     else if (format == PIXMAN_r5g6b5 ||
547              format == PIXMAN_b5g6r5)
548         c = cvt8888to0565 (c);
549
550 #if 0
551     printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
552     printf ("pixel: %x\n", c);
553 #endif
554
555     *pixel = c;
556     return TRUE;
557 }
558
559 PIXMAN_EXPORT pixman_bool_t
560 pixman_image_fill_rectangles (pixman_op_t                   op,
561                               pixman_image_t               *dest,
562                               pixman_color_t               *color,
563                               int                           n_rects,
564                               const pixman_rectangle16_t   *rects)
565 {
566     pixman_image_t *solid;
567     pixman_color_t c;
568     int i;
569
570     if (color->alpha == 0xffff)
571     {
572         if (op == PIXMAN_OP_OVER)
573             op = PIXMAN_OP_SRC;
574     }
575
576     if (op == PIXMAN_OP_CLEAR)
577     {
578         c.red = 0;
579         c.green = 0;
580         c.blue = 0;
581         c.alpha = 0;
582
583         color = &c;
584
585         op = PIXMAN_OP_SRC;
586     }
587
588     if (op == PIXMAN_OP_SRC)
589     {
590         uint32_t pixel;
591
592         if (color_to_pixel (color, &pixel, dest->bits.format))
593         {
594             for (i = 0; i < n_rects; ++i)
595             {
596                 pixman_region32_t fill_region;
597                 int n_boxes, j;
598                 pixman_box32_t *boxes;
599
600                 pixman_region32_init_rect (&fill_region, rects[i].x, rects[i].y, rects[i].width, rects[i].height);
601
602                 if (dest->common.have_clip_region)
603                 {
604                     if (!pixman_region32_intersect (&fill_region,
605                                                     &fill_region,
606                                                     &dest->common.clip_region))
607                         return FALSE;
608                 }
609
610                 boxes = pixman_region32_rectangles (&fill_region, &n_boxes);
611                 for (j = 0; j < n_boxes; ++j)
612                 {
613                     const pixman_box32_t *box = &(boxes[j]);
614                     pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
615                                  box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1,
616                                  pixel);
617                 }
618
619                 pixman_region32_fini (&fill_region);
620             }
621             return TRUE;
622         }
623     }
624
625     solid = pixman_image_create_solid_fill (color);
626     if (!solid)
627         return FALSE;
628
629     for (i = 0; i < n_rects; ++i)
630     {
631         const pixman_rectangle16_t *rect = &(rects[i]);
632
633         pixman_image_composite (op, solid, NULL, dest,
634                                 0, 0, 0, 0,
635                                 rect->x, rect->y,
636                                 rect->width, rect->height);
637     }
638
639     pixman_image_unref (solid);
640
641     return TRUE;
642 }
643
644 pixman_bool_t
645 pixman_image_can_get_solid (pixman_image_t *image)
646 {
647     if (image->type == SOLID)
648         return TRUE;
649
650     if (image->type != BITS     ||
651         image->bits.width != 1  ||
652         image->bits.height != 1)
653     {
654         return FALSE;
655     }
656
657     if (image->common.repeat != PIXMAN_REPEAT_NORMAL)
658         return FALSE;
659
660     switch (image->bits.format)
661     {
662     case PIXMAN_a8r8g8b8:
663     case PIXMAN_x8r8g8b8:
664     case PIXMAN_a8b8g8r8:
665     case PIXMAN_x8b8g8r8:
666     case PIXMAN_b8g8r8a8:
667     case PIXMAN_b8g8r8x8:
668     case PIXMAN_r8g8b8:
669     case PIXMAN_b8g8r8:
670     case PIXMAN_r5g6b5:
671     case PIXMAN_b5g6r5:
672         return TRUE;
673     default:
674         return FALSE;
675     }
676 }
677
678 pixman_bool_t
679 pixman_image_is_opaque (pixman_image_t *image)
680 {
681     int i;
682
683     if (image->common.alpha_map)
684         return FALSE;
685
686     switch (image->type)
687     {
688     case BITS:
689         if (image->common.repeat == PIXMAN_REPEAT_NONE)
690             return FALSE;
691         
692         if (PIXMAN_FORMAT_A (image->bits.format))
693             return FALSE;
694         break;
695
696     case LINEAR:
697     case RADIAL:
698         if (image->common.repeat == PIXMAN_REPEAT_NONE)
699             return FALSE;
700         
701         for (i = 0; i < image->gradient.n_stops; ++i)
702         {
703             if (image->gradient.stops[i].color.alpha != 0xffff)
704                 return FALSE;
705         }
706         break;
707
708     case CONICAL:
709         /* Conical gradients always have a transparent border */
710         return FALSE;
711         break;
712         
713     case SOLID:
714          if (Alpha (image->solid.color) != 0xff)
715             return FALSE;
716         break;
717     }
718
719     /* Convolution filters can introduce translucency if the sum of the
720      * weights is lower than 1.
721      */
722     if (image->common.filter == PIXMAN_FILTER_CONVOLUTION)
723          return FALSE;
724
725      return TRUE;
726 }