Allow NULL property_changed function
[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 #include "pixman-combine32.h"
34
35 pixman_bool_t
36 _pixman_init_gradient (gradient_t *                  gradient,
37                        const pixman_gradient_stop_t *stops,
38                        int                           n_stops)
39 {
40     return_val_if_fail (n_stops > 0, FALSE);
41
42     gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t));
43     if (!gradient->stops)
44         return FALSE;
45
46     memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
47
48     gradient->n_stops = n_stops;
49
50     return TRUE;
51 }
52
53 pixman_image_t *
54 _pixman_image_allocate (void)
55 {
56     pixman_image_t *image = malloc (sizeof (pixman_image_t));
57
58     if (image)
59     {
60         image_common_t *common = &image->common;
61
62         pixman_region32_init (&common->clip_region);
63
64         common->alpha_count = 0;
65         common->have_clip_region = FALSE;
66         common->clip_sources = FALSE;
67         common->transform = NULL;
68         common->repeat = PIXMAN_REPEAT_NONE;
69         common->filter = PIXMAN_FILTER_NEAREST;
70         common->filter_params = NULL;
71         common->n_filter_params = 0;
72         common->alpha_map = NULL;
73         common->component_alpha = FALSE;
74         common->ref_count = 1;
75         common->classify = NULL;
76         common->property_changed = NULL;
77         common->client_clip = FALSE;
78         common->destroy_func = NULL;
79         common->destroy_data = NULL;
80         common->dirty = TRUE;
81     }
82
83     return image;
84 }
85
86 source_image_class_t
87 _pixman_image_classify (pixman_image_t *image,
88                         int             x,
89                         int             y,
90                         int             width,
91                         int             height)
92 {
93     if (image->common.classify)
94         return image->common.classify (image, x, y, width, height);
95     else
96         return SOURCE_IMAGE_CLASS_UNKNOWN;
97 }
98
99 static void
100 image_property_changed (pixman_image_t *image)
101 {
102     image->common.dirty = TRUE;
103 }
104
105 /* Ref Counting */
106 PIXMAN_EXPORT pixman_image_t *
107 pixman_image_ref (pixman_image_t *image)
108 {
109     image->common.ref_count++;
110
111     return image;
112 }
113
114 /* returns TRUE when the image is freed */
115 PIXMAN_EXPORT pixman_bool_t
116 pixman_image_unref (pixman_image_t *image)
117 {
118     image_common_t *common = (image_common_t *)image;
119
120     common->ref_count--;
121
122     if (common->ref_count == 0)
123     {
124         if (image->common.destroy_func)
125             image->common.destroy_func (image, image->common.destroy_data);
126
127         pixman_region32_fini (&common->clip_region);
128
129         if (common->transform)
130             free (common->transform);
131
132         if (common->filter_params)
133             free (common->filter_params);
134
135         if (common->alpha_map)
136             pixman_image_unref ((pixman_image_t *)common->alpha_map);
137
138         if (image->type == LINEAR ||
139             image->type == RADIAL ||
140             image->type == CONICAL)
141         {
142             if (image->gradient.stops)
143                 free (image->gradient.stops);
144         }
145
146         if (image->type == BITS && image->bits.free_me)
147             free (image->bits.free_me);
148
149         free (image);
150
151         return TRUE;
152     }
153
154     return FALSE;
155 }
156
157 PIXMAN_EXPORT void
158 pixman_image_set_destroy_function (pixman_image_t *            image,
159                                    pixman_image_destroy_func_t func,
160                                    void *                      data)
161 {
162     image->common.destroy_func = func;
163     image->common.destroy_data = data;
164 }
165
166 PIXMAN_EXPORT void *
167 pixman_image_get_destroy_data (pixman_image_t *image)
168 {
169   return image->common.destroy_data;
170 }
171
172 void
173 _pixman_image_reset_clip_region (pixman_image_t *image)
174 {
175     image->common.have_clip_region = FALSE;
176 }
177
178 /* Executive Summary: This function is a no-op that only exists
179  * for historical reasons.
180  *
181  * There used to be a bug in the X server where it would rely on
182  * out-of-bounds accesses when it was asked to composite with a
183  * window as the source. It would create a pixman image pointing
184  * to some bogus position in memory, but then set a clip region
185  * to the position where the actual bits were.
186  *
187  * Due to a bug in old versions of pixman, where it would not clip
188  * against the image bounds when a clip region was set, this would
189  * actually work. So when the pixman bug was fixed, a workaround was
190  * added to allow certain out-of-bound accesses. This function disabled
191  * those workarounds.
192  *
193  * Since 0.21.2, pixman doesn't do these workarounds anymore, so now
194  * this function is a no-op.
195  */
196 PIXMAN_EXPORT void
197 pixman_disable_out_of_bounds_workaround (void)
198 {
199 }
200
201 static void
202 compute_image_info (pixman_image_t *image)
203 {
204     pixman_format_code_t code;
205     uint32_t flags = 0;
206
207     /* Transform */
208     if (!image->common.transform)
209     {
210         flags |= (FAST_PATH_ID_TRANSFORM        |
211                   FAST_PATH_X_UNIT_POSITIVE     |
212                   FAST_PATH_Y_UNIT_ZERO         |
213                   FAST_PATH_AFFINE_TRANSFORM);
214     }
215     else
216     {
217         flags |= FAST_PATH_HAS_TRANSFORM;
218
219         if (image->common.transform->matrix[2][0] == 0                  &&
220             image->common.transform->matrix[2][1] == 0                  &&
221             image->common.transform->matrix[2][2] == pixman_fixed_1)
222         {
223             flags |= FAST_PATH_AFFINE_TRANSFORM;
224
225             if (image->common.transform->matrix[0][1] == 0 &&
226                 image->common.transform->matrix[1][0] == 0)
227             {
228                 flags |= FAST_PATH_SCALE_TRANSFORM;
229             }
230         }
231
232         if (image->common.transform->matrix[0][0] > 0)
233             flags |= FAST_PATH_X_UNIT_POSITIVE;
234
235         if (image->common.transform->matrix[1][0] == 0)
236             flags |= FAST_PATH_Y_UNIT_ZERO;
237     }
238
239     /* Filter */
240     switch (image->common.filter)
241     {
242     case PIXMAN_FILTER_NEAREST:
243     case PIXMAN_FILTER_FAST:
244         flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
245         break;
246
247     case PIXMAN_FILTER_BILINEAR:
248     case PIXMAN_FILTER_GOOD:
249     case PIXMAN_FILTER_BEST:
250         flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
251         break;
252
253     case PIXMAN_FILTER_CONVOLUTION:
254         break;
255
256     default:
257         flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
258         break;
259     }
260
261     /* Repeat mode */
262     switch (image->common.repeat)
263     {
264     case PIXMAN_REPEAT_NONE:
265         flags |=
266             FAST_PATH_NO_REFLECT_REPEAT         |
267             FAST_PATH_NO_PAD_REPEAT             |
268             FAST_PATH_NO_NORMAL_REPEAT;
269         break;
270
271     case PIXMAN_REPEAT_REFLECT:
272         flags |=
273             FAST_PATH_NO_PAD_REPEAT             |
274             FAST_PATH_NO_NONE_REPEAT            |
275             FAST_PATH_NO_NORMAL_REPEAT;
276         break;
277
278     case PIXMAN_REPEAT_PAD:
279         flags |=
280             FAST_PATH_NO_REFLECT_REPEAT         |
281             FAST_PATH_NO_NONE_REPEAT            |
282             FAST_PATH_NO_NORMAL_REPEAT;
283         break;
284
285     default:
286         flags |=
287             FAST_PATH_NO_REFLECT_REPEAT         |
288             FAST_PATH_NO_PAD_REPEAT             |
289             FAST_PATH_NO_NONE_REPEAT;
290         break;
291     }
292
293     /* Component alpha */
294     if (image->common.component_alpha)
295         flags |= FAST_PATH_COMPONENT_ALPHA;
296     else
297         flags |= FAST_PATH_UNIFIED_ALPHA;
298
299     flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);
300
301     /* Type specific checks */
302     switch (image->type)
303     {
304     case SOLID:
305         code = PIXMAN_solid;
306
307         if (image->solid.color.alpha == 0xffff)
308             flags |= FAST_PATH_IS_OPAQUE;
309         break;
310
311     case BITS:
312         if (image->bits.width == 1      &&
313             image->bits.height == 1     &&
314             image->common.repeat != PIXMAN_REPEAT_NONE)
315         {
316             code = PIXMAN_solid;
317         }
318         else
319         {
320             code = image->bits.format;
321         }
322
323         if (!PIXMAN_FORMAT_A (image->bits.format)                               &&
324             PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY         &&
325             PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR)
326         {
327             flags |= FAST_PATH_SAMPLES_OPAQUE;
328
329             if (image->common.repeat != PIXMAN_REPEAT_NONE)
330                 flags |= FAST_PATH_IS_OPAQUE;
331         }
332
333         if (image->bits.read_func || image->bits.write_func)
334             flags &= ~FAST_PATH_NO_ACCESSORS;
335
336         if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
337             flags &= ~FAST_PATH_NARROW_FORMAT;
338         break;
339
340     case RADIAL:
341         code = PIXMAN_unknown;
342
343         /*
344          * As explained in pixman-radial-gradient.c, every point of
345          * the plane has a valid associated radius (and thus will be
346          * colored) if and only if a is negative (i.e. one of the two
347          * circles contains the other one).
348          */
349
350         if (image->radial.a >= 0)
351             break;
352
353         /* Fall through */
354
355     case CONICAL:
356     case LINEAR:
357         code = PIXMAN_unknown;
358
359         if (image->common.repeat != PIXMAN_REPEAT_NONE)
360         {
361             int i;
362
363             flags |= FAST_PATH_IS_OPAQUE;
364             for (i = 0; i < image->gradient.n_stops; ++i)
365             {
366                 if (image->gradient.stops[i].color.alpha != 0xffff)
367                 {
368                     flags &= ~FAST_PATH_IS_OPAQUE;
369                     break;
370                 }
371             }
372         }
373         break;
374
375     default:
376         code = PIXMAN_unknown;
377         break;
378     }
379
380     /* Alpha map */
381     if (!image->common.alpha_map)
382     {
383         flags |= FAST_PATH_NO_ALPHA_MAP;
384     }
385     else
386     {
387         if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
388             flags &= ~FAST_PATH_NARROW_FORMAT;
389     }
390
391     /* Both alpha maps and convolution filters can introduce
392      * non-opaqueness in otherwise opaque images. Also
393      * an image with component alpha turned on is only opaque
394      * if all channels are opaque, so we simply turn it off
395      * unconditionally for those images.
396      */
397     if (image->common.alpha_map                                 ||
398         image->common.filter == PIXMAN_FILTER_CONVOLUTION       ||
399         image->common.component_alpha)
400     {
401         flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
402     }
403
404     image->common.flags = flags;
405     image->common.extended_format_code = code;
406 }
407
408 void
409 _pixman_image_validate (pixman_image_t *image)
410 {
411     if (image->common.dirty)
412     {
413         compute_image_info (image);
414
415         /* It is important that property_changed is
416          * called *after* compute_image_info() because
417          * property_changed() can make use of the flags
418          * to set up accessors etc.
419          */
420         if (image->common.property_changed)
421             image->common.property_changed (image);
422
423         image->common.dirty = FALSE;
424     }
425
426     if (image->common.alpha_map)
427         _pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
428 }
429
430 PIXMAN_EXPORT pixman_bool_t
431 pixman_image_set_clip_region32 (pixman_image_t *   image,
432                                 pixman_region32_t *region)
433 {
434     image_common_t *common = (image_common_t *)image;
435     pixman_bool_t result;
436
437     if (region)
438     {
439         if ((result = pixman_region32_copy (&common->clip_region, region)))
440             image->common.have_clip_region = TRUE;
441     }
442     else
443     {
444         _pixman_image_reset_clip_region (image);
445
446         result = TRUE;
447     }
448
449     image_property_changed (image);
450
451     return result;
452 }
453
454 PIXMAN_EXPORT pixman_bool_t
455 pixman_image_set_clip_region (pixman_image_t *   image,
456                               pixman_region16_t *region)
457 {
458     image_common_t *common = (image_common_t *)image;
459     pixman_bool_t result;
460
461     if (region)
462     {
463         if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
464             image->common.have_clip_region = TRUE;
465     }
466     else
467     {
468         _pixman_image_reset_clip_region (image);
469
470         result = TRUE;
471     }
472
473     image_property_changed (image);
474
475     return result;
476 }
477
478 PIXMAN_EXPORT void
479 pixman_image_set_has_client_clip (pixman_image_t *image,
480                                   pixman_bool_t   client_clip)
481 {
482     image->common.client_clip = client_clip;
483 }
484
485 PIXMAN_EXPORT pixman_bool_t
486 pixman_image_set_transform (pixman_image_t *          image,
487                             const pixman_transform_t *transform)
488 {
489     static const pixman_transform_t id =
490     {
491         { { pixman_fixed_1, 0, 0 },
492           { 0, pixman_fixed_1, 0 },
493           { 0, 0, pixman_fixed_1 } }
494     };
495
496     image_common_t *common = (image_common_t *)image;
497     pixman_bool_t result;
498
499     if (common->transform == transform)
500         return TRUE;
501
502     if (memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
503     {
504         free (common->transform);
505         common->transform = NULL;
506         result = TRUE;
507
508         goto out;
509     }
510
511     if (common->transform == NULL)
512         common->transform = malloc (sizeof (pixman_transform_t));
513
514     if (common->transform == NULL)
515     {
516         result = FALSE;
517
518         goto out;
519     }
520
521     memcpy (common->transform, transform, sizeof(pixman_transform_t));
522
523     result = TRUE;
524
525 out:
526     image_property_changed (image);
527
528     return result;
529 }
530
531 PIXMAN_EXPORT void
532 pixman_image_set_repeat (pixman_image_t *image,
533                          pixman_repeat_t repeat)
534 {
535     image->common.repeat = repeat;
536
537     image_property_changed (image);
538 }
539
540 PIXMAN_EXPORT pixman_bool_t
541 pixman_image_set_filter (pixman_image_t *      image,
542                          pixman_filter_t       filter,
543                          const pixman_fixed_t *params,
544                          int                   n_params)
545 {
546     image_common_t *common = (image_common_t *)image;
547     pixman_fixed_t *new_params;
548
549     if (params == common->filter_params && filter == common->filter)
550         return TRUE;
551
552     new_params = NULL;
553     if (params)
554     {
555         new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
556         if (!new_params)
557             return FALSE;
558
559         memcpy (new_params,
560                 params, n_params * sizeof (pixman_fixed_t));
561     }
562
563     common->filter = filter;
564
565     if (common->filter_params)
566         free (common->filter_params);
567
568     common->filter_params = new_params;
569     common->n_filter_params = n_params;
570
571     image_property_changed (image);
572     return TRUE;
573 }
574
575 PIXMAN_EXPORT void
576 pixman_image_set_source_clipping (pixman_image_t *image,
577                                   pixman_bool_t   clip_sources)
578 {
579     image->common.clip_sources = clip_sources;
580
581     image_property_changed (image);
582 }
583
584 /* Unlike all the other property setters, this function does not
585  * copy the content of indexed. Doing this copying is simply
586  * way, way too expensive.
587  */
588 PIXMAN_EXPORT void
589 pixman_image_set_indexed (pixman_image_t *        image,
590                           const pixman_indexed_t *indexed)
591 {
592     bits_image_t *bits = (bits_image_t *)image;
593
594     bits->indexed = indexed;
595
596     image_property_changed (image);
597 }
598
599 PIXMAN_EXPORT void
600 pixman_image_set_alpha_map (pixman_image_t *image,
601                             pixman_image_t *alpha_map,
602                             int16_t         x,
603                             int16_t         y)
604 {
605     image_common_t *common = (image_common_t *)image;
606
607     return_if_fail (!alpha_map || alpha_map->type == BITS);
608
609     if (alpha_map && common->alpha_count > 0)
610     {
611         /* If this image is being used as an alpha map itself,
612          * then you can't give it an alpha map of its own.
613          */
614         return;
615     }
616
617     if (alpha_map && alpha_map->common.alpha_map)
618     {
619         /* If the image has an alpha map of its own,
620          * then it can't be used as an alpha map itself
621          */
622         return;
623     }
624
625     if (common->alpha_map != (bits_image_t *)alpha_map)
626     {
627         if (common->alpha_map)
628         {
629             common->alpha_map->common.alpha_count--;
630
631             pixman_image_unref ((pixman_image_t *)common->alpha_map);
632         }
633
634         if (alpha_map)
635         {
636             common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
637
638             common->alpha_map->common.alpha_count++;
639         }
640         else
641         {
642             common->alpha_map = NULL;
643         }
644     }
645
646     common->alpha_origin_x = x;
647     common->alpha_origin_y = y;
648
649     image_property_changed (image);
650 }
651
652 PIXMAN_EXPORT void
653 pixman_image_set_component_alpha   (pixman_image_t *image,
654                                     pixman_bool_t   component_alpha)
655 {
656     image->common.component_alpha = component_alpha;
657
658     image_property_changed (image);
659 }
660
661 PIXMAN_EXPORT pixman_bool_t
662 pixman_image_get_component_alpha   (pixman_image_t       *image)
663 {
664     return image->common.component_alpha;
665 }
666
667 PIXMAN_EXPORT void
668 pixman_image_set_accessors (pixman_image_t *           image,
669                             pixman_read_memory_func_t  read_func,
670                             pixman_write_memory_func_t write_func)
671 {
672     return_if_fail (image != NULL);
673
674     if (image->type == BITS)
675     {
676         image->bits.read_func = read_func;
677         image->bits.write_func = write_func;
678
679         image_property_changed (image);
680     }
681 }
682
683 PIXMAN_EXPORT uint32_t *
684 pixman_image_get_data (pixman_image_t *image)
685 {
686     if (image->type == BITS)
687         return image->bits.bits;
688
689     return NULL;
690 }
691
692 PIXMAN_EXPORT int
693 pixman_image_get_width (pixman_image_t *image)
694 {
695     if (image->type == BITS)
696         return image->bits.width;
697
698     return 0;
699 }
700
701 PIXMAN_EXPORT int
702 pixman_image_get_height (pixman_image_t *image)
703 {
704     if (image->type == BITS)
705         return image->bits.height;
706
707     return 0;
708 }
709
710 PIXMAN_EXPORT int
711 pixman_image_get_stride (pixman_image_t *image)
712 {
713     if (image->type == BITS)
714         return image->bits.rowstride * (int) sizeof (uint32_t);
715
716     return 0;
717 }
718
719 PIXMAN_EXPORT int
720 pixman_image_get_depth (pixman_image_t *image)
721 {
722     if (image->type == BITS)
723         return PIXMAN_FORMAT_DEPTH (image->bits.format);
724
725     return 0;
726 }
727
728 PIXMAN_EXPORT pixman_format_code_t
729 pixman_image_get_format (pixman_image_t *image)
730 {
731     if (image->type == BITS)
732         return image->bits.format;
733
734     return 0;
735 }
736
737 uint32_t
738 _pixman_image_get_solid (pixman_implementation_t *imp,
739                          pixman_image_t *         image,
740                          pixman_format_code_t     format)
741 {
742     uint32_t result;
743     pixman_iter_t iter;
744
745     _pixman_implementation_src_iter_init (
746         imp, &iter, image, 0, 0, 1, 1,
747         (uint8_t *)&result, ITER_NARROW);
748
749     result = *iter.get_scanline (&iter, NULL);
750
751     /* If necessary, convert RGB <--> BGR. */
752     if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB)
753     {
754         result = (((result & 0xff000000) >>  0) |
755                   ((result & 0x00ff0000) >> 16) |
756                   ((result & 0x0000ff00) >>  0) |
757                   ((result & 0x000000ff) << 16));
758     }
759
760     return result;
761 }