e2679623f0f47af5ae8210d03cfafa407dfd427f
[profile/ivi/pixman.git] / pixman / pixman-bits-image.c
1 /*
2  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
3  *             2005 Lars Knoll & Zack Rusin, Trolltech
4  *             2008 Aaron Plattner, NVIDIA Corporation
5  * Copyright © 2000 SuSE, Inc.
6  * Copyright © 2007, 2009 Red Hat, Inc.
7  *
8  * Permission to use, copy, modify, distribute, and sell this software and its
9  * documentation for any purpose is hereby granted without fee, provided that
10  * the above copyright notice appear in all copies and that both that
11  * copyright notice and this permission notice appear in supporting
12  * documentation, and that the name of Keith Packard not be used in
13  * advertising or publicity pertaining to distribution of the software without
14  * specific, written prior permission.  Keith Packard makes no
15  * representations about the suitability of this software for any purpose.  It
16  * is provided "as is" without express or implied warranty.
17  *
18  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
19  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
21  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
23  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
24  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
25  * SOFTWARE.
26  */
27
28 #include <config.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include "pixman-private.h"
32 #include "pixman-combine32.h"
33
34 #define Red(x) (((x) >> 16) & 0xff)
35 #define Green(x) (((x) >> 8) & 0xff)
36 #define Blue(x) ((x) & 0xff)
37
38 /* Store functions */
39
40 static void
41 bits_image_store_scanline_32 (bits_image_t *image,
42                               int x, int y,
43                               int width,
44                               const uint32_t *buffer)
45 {
46     image->store_scanline_raw_32 (image, x, y, width, buffer);
47
48     if (image->common.alpha_map)
49     {
50         x -= image->common.alpha_origin_x;
51         y -= image->common.alpha_origin_y;
52
53         bits_image_store_scanline_32 (image->common.alpha_map, x, y, width, buffer);
54     }
55 }
56
57 static void
58 bits_image_store_scanline_64 (bits_image_t *image,
59                               int x, int y,
60                               int width,
61                               const uint32_t *buffer)
62 {
63     image->store_scanline_raw_64 (image, x, y, width, buffer);
64
65     if (image->common.alpha_map)
66     {
67         x -= image->common.alpha_origin_x;
68         y -= image->common.alpha_origin_y;
69
70         bits_image_store_scanline_64 (image->common.alpha_map, x, y, width, buffer);
71     }
72 }
73
74 void
75 _pixman_image_store_scanline_32 (bits_image_t *image, int x, int y, int width,
76                                  const uint32_t *buffer)
77 {
78     image->store_scanline_32 (image, x, y, width, buffer);
79 }
80
81 void
82 _pixman_image_store_scanline_64 (bits_image_t *image, int x, int y, int width,
83                                  const uint32_t *buffer)
84 {
85     image->store_scanline_64 (image, x, y, width, buffer);
86 }
87
88 /* Fetch functions */
89
90 /* On entry, @buffer should contain @n_pixels (x, y) coordinate pairs, where
91  * x and y are both uint32_ts. On exit, buffer will contain the corresponding
92  * pixels.
93  *
94  * The coordinates must be within the sample grid. If either x or y is 0xffffffff,
95  * the pixel returned will be 0.
96  */
97 static void
98 bits_image_fetch_raw_pixels (bits_image_t *image, uint32_t *buffer, int n_pixels)
99 {
100     image->fetch_pixels_raw_32 (image, buffer, n_pixels);
101 }
102
103 static void
104 bits_image_fetch_alpha_pixels (bits_image_t *image, uint32_t *buffer, int n_pixels)
105 {
106 #define N_ALPHA_PIXELS 256
107     
108     uint32_t alpha_pixels[N_ALPHA_PIXELS * 2];
109     int i;
110     
111     if (!image->common.alpha_map)
112     {
113         bits_image_fetch_raw_pixels (image, buffer, n_pixels);
114         return;
115     }
116
117     /* Alpha map */
118     i = 0;
119     while (i < n_pixels)
120     {
121         int tmp_n_pixels = MIN (N_ALPHA_PIXELS, n_pixels - i);
122         int j;
123         int32_t *coords;
124         
125         memcpy (alpha_pixels, buffer + 2 * i, tmp_n_pixels * 2 * sizeof (int32_t));
126         coords = (int32_t *)alpha_pixels;
127         for (j = 0; j < tmp_n_pixels; ++j)
128         {
129             int32_t x = coords[0];
130             int32_t y = coords[1];
131             
132             if (x != 0xffffffff)
133             {
134                 x -= image->common.alpha_origin_x;
135                 
136                 if (x < 0 || x >= image->common.alpha_map->width)
137                     x = 0xffffffff;
138             }
139             
140             if (y != 0xffffffff)
141             {
142                 y -= image->common.alpha_origin_y;
143                 
144                 if (y < 0 || y >= image->common.alpha_map->height)
145                     y = 0xffffffff;
146             }
147             
148             coords[0] = x;
149             coords[1] = y;
150             
151             coords += 2;
152         }
153         
154         bits_image_fetch_raw_pixels (image->common.alpha_map, alpha_pixels,
155                                      tmp_n_pixels);
156         bits_image_fetch_raw_pixels (image, buffer + 2 * i, tmp_n_pixels);
157         
158         for (j = 0; j < tmp_n_pixels; ++j)
159         {
160             int a = alpha_pixels[j] >> 24;
161             uint32_t p = buffer[2 * i - j] | 0xff000000;
162
163             FbByteMul (p, a);
164
165             buffer[i++] = p;
166         }
167     }
168 }
169
170 static void
171 bits_image_fetch_pixels_src_clip (bits_image_t *image, uint32_t *buffer, int n_pixels)
172 {
173     bits_image_fetch_alpha_pixels (image, buffer, n_pixels);
174 }
175
176 static force_inline void
177 repeat (pixman_repeat_t repeat, int width, int height, int *x, int *y)
178 {
179     switch (repeat)
180     {
181     case PIXMAN_REPEAT_NORMAL:
182         *x = MOD (*x, width);
183         *y = MOD (*y, height);
184         break;
185
186     case PIXMAN_REPEAT_PAD:
187         *x = CLIP (*x, 0, width - 1);
188         *y = CLIP (*y, 0, height - 1);
189         break;
190         
191     case PIXMAN_REPEAT_REFLECT:
192         *x = MOD (*x, width * 2);
193         *y = MOD (*y, height * 2);
194
195         if (*x >= width)
196             *x = width * 2 - *x - 1;
197         
198         if (*y >= height)
199             *y = height * 2 - *y - 1;
200         break;
201
202     case PIXMAN_REPEAT_NONE:
203         if (*x < 0 || *x >= width)
204             *x = 0xffffffff;
205
206         if (*y < 0 || *y >= height)
207             *y = 0xffffffff;
208         break;
209     }
210 }
211
212 /* Buffer contains list of fixed-point coordinates on input,
213  * a list of pixels on output
214  */
215 static void
216 bits_image_fetch_nearest_pixels (bits_image_t *image, uint32_t *buffer, int n_pixels)
217 {
218     pixman_repeat_t repeat_mode = image->common.repeat;
219     int width = image->width;
220     int height = image->height;
221     int i;
222
223     for (i = 0; i < 2 * n_pixels; i += 2)
224     {
225         int32_t *coords = (int32_t *)buffer;
226         int32_t x, y;
227
228         /* Subtract pixman_fixed_e to ensure that 0.5 rounds to 0, not 1 */
229         x = pixman_fixed_to_int (coords[i] - pixman_fixed_e);
230         y = pixman_fixed_to_int (coords[i + 1] - pixman_fixed_e);
231
232         repeat (repeat_mode, width, height, &x, &y);
233
234         coords[i] = x;
235         coords[i + 1] = y;
236     }
237
238     bits_image_fetch_pixels_src_clip (image, buffer, n_pixels);
239 }
240
241 #define N_TMP_PIXELS    (256)
242
243 /* Buffer contains list of fixed-point coordinates on input,
244  * a list of pixels on output
245  */
246 static void
247 bits_image_fetch_bilinear_pixels (bits_image_t *image, uint32_t *buffer, int n_pixels)
248 {
249 /* (Four pixels * two coordinates) per pixel */
250 #define N_TEMPS         (N_TMP_PIXELS * 8)
251 #define N_DISTS         (N_TMP_PIXELS * 2)
252     
253     uint32_t temps[N_TEMPS];
254     int32_t  dists[N_DISTS];
255     pixman_repeat_t repeat_mode = image->common.repeat;
256     int width = image->width;
257     int height = image->height;
258     int32_t *coords;
259     int i;
260
261     i = 0;
262     coords = (int32_t *)buffer;
263     while (i < n_pixels)
264     {
265         int tmp_n_pixels = MIN(N_TMP_PIXELS, n_pixels - i);
266         int32_t distx, disty;
267         uint32_t *u;
268         int32_t *t, *d;
269         int j;
270         
271         t = (int32_t *)temps;
272         d = dists;
273         for (j = 0; j < tmp_n_pixels; ++j)
274         {
275             int32_t x1, y1, x2, y2;
276             
277             x1 = coords[0] - pixman_fixed_1 / 2;
278             y1 = coords[1] - pixman_fixed_1 / 2;
279             
280             distx = (x1 >> 8) & 0xff;
281             disty = (y1 >> 8) & 0xff;
282             
283             x1 >>= 16;
284             y1 >>= 16;
285             x2 = x1 + 1;
286             y2 = y1 + 1;
287
288             repeat (repeat_mode, width, height, &x1, &y1);
289             repeat (repeat_mode, width, height, &x2, &y2);
290             
291             *t++ = x1;
292             *t++ = y1;
293             *t++ = x2;
294             *t++ = y1;
295             *t++ = x1;
296             *t++ = y2;
297             *t++ = x2;
298             *t++ = y2;
299
300             *d++ = distx;
301             *d++ = disty;
302
303             coords += 2;
304         }
305
306         bits_image_fetch_pixels_src_clip (image, temps, tmp_n_pixels * 4);
307
308         u = (uint32_t *)temps;
309         d = dists;
310         for (j = 0; j < tmp_n_pixels; ++j)
311         {
312             uint32_t tl, tr, bl, br, r;
313             int32_t idistx, idisty;
314             uint32_t ft, fb;
315             
316             tl = *u++;
317             tr = *u++;
318             bl = *u++;
319             br = *u++;
320
321             distx = *d++;
322             disty = *d++;
323
324             idistx = 256 - distx;
325             idisty = 256 - disty;
326
327 #define FbGet8(v,i)   ((uint16_t) (uint8_t) ((v) >> i))
328             
329             ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
330             fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
331             r = (((ft * idisty + fb * disty) >> 16) & 0xff);
332             ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
333             fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
334             r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
335             ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
336             fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
337             r |= (((ft * idisty + fb * disty)) & 0xff0000);
338             ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
339             fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
340             r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
341
342             buffer[i++] = r;
343         }
344     }
345 }
346
347 /* Buffer contains list of fixed-point coordinates on input,
348  * a list of pixels on output
349  */
350 static void
351 bits_image_fetch_convolution_pixels (bits_image_t *image,
352                                      uint32_t *buffer, int n_pixels)
353 {
354     uint32_t tmp_pixels_stack[N_TMP_PIXELS * 2]; /* Two coordinates per pixel */
355     uint32_t *tmp_pixels = tmp_pixels_stack;
356     pixman_fixed_t *params = image->common.filter_params;
357     int x_off = (params[0] - pixman_fixed_1) >> 1;
358     int y_off = (params[1] - pixman_fixed_1) >> 1;
359     int n_tmp_pixels;
360     int32_t *coords;
361     int32_t *t;
362     uint32_t *u;
363     int i;
364     int max_n_kernels;
365
366     int32_t cwidth = pixman_fixed_to_int (params[0]);
367     int32_t cheight = pixman_fixed_to_int (params[1]);
368     int kernel_size = cwidth * cheight;
369
370     params += 2;
371
372     n_tmp_pixels = N_TMP_PIXELS;
373     if (kernel_size > n_tmp_pixels)
374     {
375         /* Two coordinates per pixel */
376         tmp_pixels = malloc (kernel_size * 2 * sizeof (uint32_t));
377         n_tmp_pixels = kernel_size;
378
379         if (!tmp_pixels)
380         {
381             /* We ignore out-of-memory during rendering */
382             return;
383         }
384     }
385
386     max_n_kernels = n_tmp_pixels / kernel_size;
387     
388     i = 0;
389     coords = (int32_t *)buffer;
390     while (i < n_pixels)
391     {
392         int n_kernels = MIN (max_n_kernels, (n_pixels - i));
393         pixman_repeat_t repeat_mode = image->common.repeat;
394         int width = image->width;
395         int height = image->height;
396         int j;
397         
398         t = (int32_t *)tmp_pixels;
399         for (j = 0; j < n_kernels; ++j)
400         {
401             int32_t x, y, x1, x2, y1, y2;
402
403             /* Subtract pixman_fixed_e to ensure that 0.5 rounds to 0, not 1 */
404             x1 = pixman_fixed_to_int (coords[0] - pixman_fixed_e - x_off);
405             y1 = pixman_fixed_to_int (coords[1] - pixman_fixed_e - y_off);
406             x2 = x1 + cwidth;
407             y2 = y1 + cheight;
408
409             for (y = y1; y < y2; ++y)
410             {
411                 for (x = x1; x < x2; ++x)
412                 {
413                     int rx = x;
414                     int ry = y;
415                     
416                     repeat (repeat_mode, width, height, &rx, &ry);
417                     
418                     *t++ = rx;
419                     *t++ = ry;
420                 }
421             }
422
423             coords += 2;
424         }
425
426         bits_image_fetch_pixels_src_clip (image, tmp_pixels, n_kernels * kernel_size);
427
428         u = tmp_pixels;
429         for (j = 0; j < n_kernels; ++j)
430         {
431             int32_t srtot, sgtot, sbtot, satot;
432             pixman_fixed_t *p = params;
433             int k;
434
435             srtot = sgtot = sbtot = satot = 0;
436                 
437             for (k = 0; k < kernel_size; ++k)
438             {
439                 pixman_fixed_t f = *p++;
440                 if (f)
441                 {
442                     uint32_t c = *u++;
443
444                     srtot += Red(c) * f;
445                     sgtot += Green(c) * f;
446                     sbtot += Blue(c) * f;
447                     satot += Alpha(c) * f;
448                 }
449             }
450
451             satot >>= 16;
452             srtot >>= 16;
453             sgtot >>= 16;
454             sbtot >>= 16;
455             
456             if (satot < 0) satot = 0; else if (satot > 0xff) satot = 0xff;
457             if (srtot < 0) srtot = 0; else if (srtot > 0xff) srtot = 0xff;
458             if (sgtot < 0) sgtot = 0; else if (sgtot > 0xff) sgtot = 0xff;
459             if (sbtot < 0) sbtot = 0; else if (sbtot > 0xff) sbtot = 0xff;
460
461             buffer[i++] = ((satot << 24) |
462                            (srtot << 16) |
463                            (sgtot <<  8) |
464                            (sbtot       ));
465         }
466     }
467     
468     if (tmp_pixels != tmp_pixels_stack)
469         free (tmp_pixels);
470 }
471
472 static void
473 bits_image_fetch_filtered (bits_image_t *pict, uint32_t *buffer, int n_pixels)
474 {
475     switch (pict->common.filter)
476     {
477     case PIXMAN_FILTER_NEAREST:
478     case PIXMAN_FILTER_FAST:
479         bits_image_fetch_nearest_pixels (pict, buffer, n_pixels);
480         break;
481         
482     case PIXMAN_FILTER_BILINEAR:
483     case PIXMAN_FILTER_GOOD:
484     case PIXMAN_FILTER_BEST:
485         bits_image_fetch_bilinear_pixels (pict, buffer, n_pixels);
486         break;
487         
488     case PIXMAN_FILTER_CONVOLUTION:
489         bits_image_fetch_convolution_pixels (pict, buffer, n_pixels);
490         break;
491     }
492 }
493
494 static void
495 bits_image_fetch_transformed (pixman_image_t * pict, int x, int y, int width,
496                               uint32_t *buffer, uint32_t *mask,
497                               uint32_t maskBits)
498 {
499     uint32_t     *bits;
500     int32_t    stride;
501     pixman_vector_t v;
502     pixman_vector_t unit;
503     pixman_bool_t affine = TRUE;
504     uint32_t tmp_buffer[2 * N_TMP_PIXELS];
505     int32_t *coords;
506     int i;
507
508     bits = pict->bits.bits;
509     stride = pict->bits.rowstride;
510
511     /* reference point is the center of the pixel */
512     v.vector[0] = pixman_int_to_fixed(x) + pixman_fixed_1 / 2;
513     v.vector[1] = pixman_int_to_fixed(y) + pixman_fixed_1 / 2;
514     v.vector[2] = pixman_fixed_1;
515
516     /* when using convolution filters or PIXMAN_REPEAT_PAD one
517      * might get here without a transform */
518     if (pict->common.transform)
519     {
520         if (!pixman_transform_point_3d (pict->common.transform, &v))
521             return;
522         
523         unit.vector[0] = pict->common.transform->matrix[0][0];
524         unit.vector[1] = pict->common.transform->matrix[1][0];
525         unit.vector[2] = pict->common.transform->matrix[2][0];
526
527         affine = (v.vector[2] == pixman_fixed_1 && unit.vector[2] == 0);
528     }
529     else
530     {
531         unit.vector[0] = pixman_fixed_1;
532         unit.vector[1] = 0;
533         unit.vector[2] = 0;
534     }
535
536     i = 0;
537     while (i < width)
538     {
539         int n_pixels = MIN (N_TMP_PIXELS, width - i);
540         int j;
541         
542         coords = (int32_t *)tmp_buffer;
543
544         for (j = 0; j < n_pixels; ++j)
545         {
546             if (affine)
547             {
548                 coords[0] = v.vector[0];
549                 coords[1] = v.vector[1];
550             }
551             else
552             {
553                 pixman_fixed_48_16_t div;
554                 
555                 div = ((pixman_fixed_48_16_t)v.vector[0] << 16) / v.vector[2];
556
557                 if ((div >> 16) > 0x7fff)
558                     coords[0] = 0x7fffffff; 
559                 else if ((div >> 16) < 0x8000)
560                     coords[0] = 0x80000000;
561                 else
562                     coords[0] = div;
563                 
564                 div = ((pixman_fixed_48_16_t)v.vector[1] << 16) / v.vector[2];
565
566                 if ((div >> 16) > 0x7fff)
567                     coords[1] = 0x7fffffff;
568                 else if ((div >> 16) < 0x8000)
569                     coords[1] = 0x8000000;
570                 else
571                     coords[1] = div;
572
573                 v.vector[2] += unit.vector[2];
574             }
575
576             coords += 2;
577
578             v.vector[0] += unit.vector[0];
579             v.vector[1] += unit.vector[1];
580         }
581
582         bits_image_fetch_filtered (&pict->bits, tmp_buffer, n_pixels);
583         
584         for (j = 0; j < n_pixels; ++j)
585             buffer[i++] = tmp_buffer[j];
586     }
587 }
588
589 static void
590 bits_image_fetch_solid_32 (pixman_image_t * image,
591                            int x, int y, int width,
592                            uint32_t *buffer,
593                            uint32_t *mask, uint32_t maskBits)
594 {
595     uint32_t color[2];
596     uint32_t *end;
597
598     color[0] = 0;
599     color[1] = 0;
600     
601     image->bits.fetch_pixels_raw_32 (&image->bits, color, 1);
602     
603     end = buffer + width;
604     while (buffer < end)
605         *(buffer++) = color[0];
606 }
607
608 static void
609 bits_image_fetch_solid_64 (pixman_image_t * image,
610                            int x, int y, int width,
611                            uint32_t *b,
612                            uint32_t *unused,
613                            uint32_t unused2)
614 {
615     uint32_t color[2];
616     uint32_t *coords = (uint32_t *)color;
617     uint64_t *buffer = (uint64_t *)b;
618     uint64_t *end;
619     
620     coords[0] = 0;
621     coords[1] = 1;
622     
623     image->bits.fetch_pixels_raw_64 (&image->bits, color, 1);
624     
625     end = buffer + width;
626     while (buffer < end)
627         *(buffer++) = color[0];
628 }
629
630 static void
631 bits_image_fetch_untransformed_repeat_none (bits_image_t *image, pixman_bool_t wide,
632                                             int x, int y, int width,
633                                             uint32_t *buffer)
634 {
635     uint32_t w;
636
637     if (y < 0 || y >= image->height)
638     {
639         memset (buffer, 0, width * sizeof (uint32_t));
640         return;
641     }
642
643     if (x < 0)
644     {
645         w = MIN (width, -x);
646         
647         memset (buffer, 0, w * (wide? 8 : 4));
648         
649         width -= w;
650         buffer += w;
651         x += w;
652     }
653     
654     if (x < image->width)
655     {
656         w = MIN (width, image->width - x);
657         
658         if (wide)
659             image->fetch_scanline_raw_64 (image, x, y, w, buffer, NULL, 0);
660         else
661             image->fetch_scanline_raw_32 (image, x, y, w, buffer, NULL, 0);
662         
663         width -= w;
664         buffer += w;
665         x += w;
666     }
667
668     memset (buffer, 0, width * (wide? 8 : 4));
669 }
670
671 static void
672 bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, pixman_bool_t wide,
673                                               int x, int y, int width,
674                                               uint32_t *buffer)
675 {
676     uint32_t w;
677     
678     while (y < 0)
679         y += image->height;
680     while (y >= image->height)
681         y -= image->height;
682     
683     while (width)
684     {
685         while (x < 0)
686             x += image->width;
687         while (x >= image->width)
688             x -= image->width;
689         
690         w = MIN (width, image->width - x);
691         
692         if (wide)
693             image->fetch_scanline_raw_64 (image, x, y, w, buffer, NULL, 0);
694         else
695             image->fetch_scanline_raw_32 (image, x, y, w, buffer, NULL, 0);
696         
697         buffer += w;
698         x += w;
699         width -= w;
700     }
701 }
702
703 static void
704 bits_image_fetch_untransformed_32 (pixman_image_t * image,
705                                    int x, int y, int width,
706                                    uint32_t *buffer,
707                                    uint32_t *mask, uint32_t maskBits)
708 {
709     if (image->common.repeat == PIXMAN_REPEAT_NONE)
710     {
711         bits_image_fetch_untransformed_repeat_none (
712             &image->bits, FALSE, x, y, width, buffer);
713     }
714     else
715     {
716         bits_image_fetch_untransformed_repeat_normal (
717             &image->bits, FALSE, x, y, width, buffer);
718     }
719 }
720
721 static void
722 bits_image_fetch_untransformed_64 (pixman_image_t * image,
723                                    int x, int y, int width,
724                                    uint32_t *buffer,
725                                    uint32_t *unused, uint32_t unused2)
726 {
727     if (image->common.repeat == PIXMAN_REPEAT_NONE)
728     {
729         bits_image_fetch_untransformed_repeat_none (
730             &image->bits, TRUE, x, y, width, buffer);
731     }
732     else
733     {
734         bits_image_fetch_untransformed_repeat_normal (
735             &image->bits, TRUE, x, y, width, buffer);
736     }
737 }
738
739 static void
740 bits_image_property_changed (pixman_image_t *image)
741 {
742     bits_image_t *bits = (bits_image_t *)image;
743     
744     _pixman_bits_image_setup_raw_accessors (bits);
745
746     if (bits->common.alpha_map)
747     {
748         image->common.get_scanline_64 =
749             _pixman_image_get_scanline_64_generic;
750         image->common.get_scanline_32 =
751             bits_image_fetch_transformed;
752     }
753     else if ((bits->common.repeat != PIXMAN_REPEAT_NONE) &&
754             bits->width == 1 &&
755             bits->height == 1)
756     {
757         image->common.get_scanline_64 = bits_image_fetch_solid_64;
758         image->common.get_scanline_32 = bits_image_fetch_solid_32;
759     }
760     else if (!bits->common.transform &&
761              bits->common.filter != PIXMAN_FILTER_CONVOLUTION &&
762              (bits->common.repeat == PIXMAN_REPEAT_NONE ||
763               bits->common.repeat == PIXMAN_REPEAT_NORMAL))
764     {
765         image->common.get_scanline_64 =
766             bits_image_fetch_untransformed_64;
767         image->common.get_scanline_32 =
768             bits_image_fetch_untransformed_32;
769     }
770     else
771     {
772         image->common.get_scanline_64 =
773             _pixman_image_get_scanline_64_generic;
774         image->common.get_scanline_32 =
775             bits_image_fetch_transformed;
776     }
777
778     bits->store_scanline_64 = bits_image_store_scanline_64;
779     bits->store_scanline_32 = bits_image_store_scanline_32;
780 }
781
782 static uint32_t *
783 create_bits (pixman_format_code_t format,
784              int                  width,
785              int                  height,
786              int                 *rowstride_bytes)
787 {
788     int stride;
789     int buf_size;
790     int bpp;
791     
792     /* what follows is a long-winded way, avoiding any possibility of integer
793      * overflows, of saying:
794      * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t);
795      */
796     
797     bpp = PIXMAN_FORMAT_BPP (format);
798     if (pixman_multiply_overflows_int (width, bpp))
799         return NULL;
800     
801     stride = width * bpp;
802     if (pixman_addition_overflows_int (stride, 0x1f))
803         return NULL;
804     
805     stride += 0x1f;
806     stride >>= 5;
807     
808     stride *= sizeof (uint32_t);
809     
810     if (pixman_multiply_overflows_int (height, stride))
811         return NULL;
812     
813     buf_size = height * stride;
814     
815     if (rowstride_bytes)
816         *rowstride_bytes = stride;
817     
818     return calloc (buf_size, 1);
819 }
820
821 PIXMAN_EXPORT pixman_image_t *
822 pixman_image_create_bits (pixman_format_code_t  format,
823                           int                   width,
824                           int                   height,
825                           uint32_t             *bits,
826                           int                   rowstride_bytes)
827 {
828     pixman_image_t *image;
829     uint32_t *free_me = NULL;
830     
831     /* must be a whole number of uint32_t's
832      */
833     return_val_if_fail (bits == NULL ||
834                         (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
835     
836     if (!bits && width && height)
837     {
838         free_me = bits = create_bits (format, width, height, &rowstride_bytes);
839         if (!bits)
840             return NULL;
841     }
842     
843     image = _pixman_image_allocate();
844     
845     if (!image) {
846         if (free_me)
847             free (free_me);
848         return NULL;
849     }
850     
851     image->type = BITS;
852     image->bits.format = format;
853     image->bits.width = width;
854     image->bits.height = height;
855     image->bits.bits = bits;
856     image->bits.free_me = free_me;
857
858     /* The rowstride is stored in number of uint32_t */
859     image->bits.rowstride = rowstride_bytes / (int) sizeof (uint32_t);
860     
861     image->bits.indexed = NULL;
862     
863     image->common.property_changed = bits_image_property_changed;
864     
865     bits_image_property_changed (image);
866     
867     _pixman_image_reset_clip_region (image);
868     
869     return image;
870 }