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