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