Move calls to source_is_fastpathable() into get_source_format()
[profile/ivi/pixman.git] / pixman / pixman-utils.c
1 /*
2  * Copyright © 2000 SuSE, Inc.
3  * Copyright © 1999 Keith Packard
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  * Author:  Keith Packard, SuSE, Inc.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 #include "pixman-private.h"
32
33 /*
34  * Computing composite region
35  */
36 static inline pixman_bool_t
37 clip_general_image (pixman_region32_t * region,
38                     pixman_region32_t * clip,
39                     int                 dx,
40                     int                 dy)
41 {
42     if (pixman_region32_n_rects (region) == 1 &&
43         pixman_region32_n_rects (clip) == 1)
44     {
45         pixman_box32_t *  rbox = pixman_region32_rectangles (region, NULL);
46         pixman_box32_t *  cbox = pixman_region32_rectangles (clip, NULL);
47         int v;
48
49         if (rbox->x1 < (v = cbox->x1 + dx))
50             rbox->x1 = v;
51         if (rbox->x2 > (v = cbox->x2 + dx))
52             rbox->x2 = v;
53         if (rbox->y1 < (v = cbox->y1 + dy))
54             rbox->y1 = v;
55         if (rbox->y2 > (v = cbox->y2 + dy))
56             rbox->y2 = v;
57         if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
58         {
59             pixman_region32_init (region);
60             return FALSE;
61         }
62     }
63     else if (!pixman_region32_not_empty (clip))
64     {
65         return FALSE;
66     }
67     else
68     {
69         if (dx || dy)
70             pixman_region32_translate (region, -dx, -dy);
71
72         if (!pixman_region32_intersect (region, region, clip))
73             return FALSE;
74
75         if (dx || dy)
76             pixman_region32_translate (region, dx, dy);
77     }
78
79     return pixman_region32_not_empty (region);
80 }
81
82 static inline pixman_bool_t
83 clip_source_image (pixman_region32_t * region,
84                    pixman_image_t *    image,
85                    int                 dx,
86                    int                 dy)
87 {
88     /* Source clips are ignored, unless they are explicitly turned on
89      * and the clip in question was set by an X client. (Because if
90      * the clip was not set by a client, then it is a hierarchy
91      * clip and those should always be ignored for sources).
92      */
93     if (!image->common.clip_sources || !image->common.client_clip)
94         return TRUE;
95
96     return clip_general_image (region,
97                                &image->common.clip_region,
98                                dx, dy);
99 }
100
101 /*
102  * returns FALSE if the final region is empty.  Indistinguishable from
103  * an allocation failure, but rendering ignores those anyways.
104  */
105 static pixman_bool_t
106 pixman_compute_composite_region32 (pixman_region32_t * region,
107                                    pixman_image_t *    src_image,
108                                    pixman_image_t *    mask_image,
109                                    pixman_image_t *    dst_image,
110                                    int32_t             src_x,
111                                    int32_t             src_y,
112                                    int32_t             mask_x,
113                                    int32_t             mask_y,
114                                    int32_t             dest_x,
115                                    int32_t             dest_y,
116                                    int32_t             width,
117                                    int32_t             height)
118 {
119     region->extents.x1 = dest_x;
120     region->extents.x2 = dest_x + width;
121     region->extents.y1 = dest_y;
122     region->extents.y2 = dest_y + height;
123
124     region->extents.x1 = MAX (region->extents.x1, 0);
125     region->extents.y1 = MAX (region->extents.y1, 0);
126     region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
127     region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
128
129     region->data = 0;
130
131     /* Check for empty operation */
132     if (region->extents.x1 >= region->extents.x2 ||
133         region->extents.y1 >= region->extents.y2)
134     {
135         pixman_region32_init (region);
136         return FALSE;
137     }
138
139     if (dst_image->common.have_clip_region)
140     {
141         if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
142         {
143             pixman_region32_fini (region);
144             return FALSE;
145         }
146     }
147
148     if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region)
149     {
150         if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
151                                  -dst_image->common.alpha_origin_x,
152                                  -dst_image->common.alpha_origin_y))
153         {
154             pixman_region32_fini (region);
155             return FALSE;
156         }
157     }
158
159     /* clip against src */
160     if (src_image->common.have_clip_region)
161     {
162         if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
163         {
164             pixman_region32_fini (region);
165             return FALSE;
166         }
167     }
168     if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
169     {
170         if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
171                                 dest_x - (src_x - src_image->common.alpha_origin_x),
172                                 dest_y - (src_y - src_image->common.alpha_origin_y)))
173         {
174             pixman_region32_fini (region);
175             return FALSE;
176         }
177     }
178     /* clip against mask */
179     if (mask_image && mask_image->common.have_clip_region)
180     {
181         if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
182         {
183             pixman_region32_fini (region);
184             return FALSE;
185         }
186         if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
187         {
188             if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
189                                     dest_x - (mask_x - mask_image->common.alpha_origin_x),
190                                     dest_y - (mask_y - mask_image->common.alpha_origin_y)))
191             {
192                 pixman_region32_fini (region);
193                 return FALSE;
194             }
195         }
196     }
197
198     return TRUE;
199 }
200
201 PIXMAN_EXPORT pixman_bool_t
202 pixman_compute_composite_region (pixman_region16_t * region,
203                                  pixman_image_t *    src_image,
204                                  pixman_image_t *    mask_image,
205                                  pixman_image_t *    dst_image,
206                                  int16_t             src_x,
207                                  int16_t             src_y,
208                                  int16_t             mask_x,
209                                  int16_t             mask_y,
210                                  int16_t             dest_x,
211                                  int16_t             dest_y,
212                                  uint16_t            width,
213                                  uint16_t            height)
214 {
215     pixman_region32_t r32;
216     pixman_bool_t retval;
217
218     pixman_region32_init (&r32);
219
220     retval = pixman_compute_composite_region32 (
221         &r32, src_image, mask_image, dst_image,
222         src_x, src_y, mask_x, mask_y, dest_x, dest_y,
223         width, height);
224
225     if (retval)
226     {
227         if (!pixman_region16_copy_from_region32 (region, &r32))
228             retval = FALSE;
229     }
230
231     pixman_region32_fini (&r32);
232     return retval;
233 }
234
235 pixman_bool_t
236 pixman_multiply_overflows_int (unsigned int a,
237                                unsigned int b)
238 {
239     return a >= INT32_MAX / b;
240 }
241
242 pixman_bool_t
243 pixman_addition_overflows_int (unsigned int a,
244                                unsigned int b)
245 {
246     return a > INT32_MAX - b;
247 }
248
249 void *
250 pixman_malloc_ab (unsigned int a,
251                   unsigned int b)
252 {
253     if (a >= INT32_MAX / b)
254         return NULL;
255
256     return malloc (a * b);
257 }
258
259 void *
260 pixman_malloc_abc (unsigned int a,
261                    unsigned int b,
262                    unsigned int c)
263 {
264     if (a >= INT32_MAX / b)
265         return NULL;
266     else if (a * b >= INT32_MAX / c)
267         return NULL;
268     else
269         return malloc (a * b * c);
270 }
271
272 /*
273  * Helper routine to expand a color component from 0 < n <= 8 bits to 16
274  * bits by replication.
275  */
276 static inline uint64_t
277 expand16 (const uint8_t val, int nbits)
278 {
279     /* Start out with the high bit of val in the high bit of result. */
280     uint16_t result = (uint16_t)val << (16 - nbits);
281
282     if (nbits == 0)
283         return 0;
284
285     /* Copy the bits in result, doubling the number of bits each time, until
286      * we fill all 16 bits.
287      */
288     while (nbits < 16)
289     {
290         result |= result >> nbits;
291         nbits *= 2;
292     }
293
294     return result;
295 }
296
297 /*
298  * This function expands images from ARGB8 format to ARGB16.  To preserve
299  * precision, it needs to know the original source format.  For example, if the
300  * source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then
301  * the expanded value is 12345123.  To correctly expand this to 16 bits, it
302  * should be 1234512345123451 and not 1234512312345123.
303  */
304 void
305 pixman_expand (uint64_t *           dst,
306                const uint32_t *     src,
307                pixman_format_code_t format,
308                int                  width)
309 {
310     /*
311      * Determine the sizes of each component and the masks and shifts
312      * required to extract them from the source pixel.
313      */
314     const int a_size = PIXMAN_FORMAT_A (format),
315               r_size = PIXMAN_FORMAT_R (format),
316               g_size = PIXMAN_FORMAT_G (format),
317               b_size = PIXMAN_FORMAT_B (format);
318     const int a_shift = 32 - a_size,
319               r_shift = 24 - r_size,
320               g_shift = 16 - g_size,
321               b_shift =  8 - b_size;
322     const uint8_t a_mask = ~(~0 << a_size),
323                   r_mask = ~(~0 << r_size),
324                   g_mask = ~(~0 << g_size),
325                   b_mask = ~(~0 << b_size);
326     int i;
327
328     /* Start at the end so that we can do the expansion in place
329      * when src == dst
330      */
331     for (i = width - 1; i >= 0; i--)
332     {
333         const uint32_t pixel = src[i];
334         const uint8_t a = (pixel >> a_shift) & a_mask,
335                       r = (pixel >> r_shift) & r_mask,
336                       g = (pixel >> g_shift) & g_mask,
337                       b = (pixel >> b_shift) & b_mask;
338         const uint64_t a16 = a_size ? expand16 (a, a_size) : 0xffff,
339                        r16 = expand16 (r, r_size),
340                        g16 = expand16 (g, g_size),
341                        b16 = expand16 (b, b_size);
342
343         dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16;
344     }
345 }
346
347 /*
348  * Contracting is easier than expanding.  We just need to truncate the
349  * components.
350  */
351 void
352 pixman_contract (uint32_t *      dst,
353                  const uint64_t *src,
354                  int             width)
355 {
356     int i;
357
358     /* Start at the beginning so that we can do the contraction in
359      * place when src == dst
360      */
361     for (i = 0; i < width; i++)
362     {
363         const uint8_t a = src[i] >> 56,
364                       r = src[i] >> 40,
365                       g = src[i] >> 24,
366                       b = src[i] >> 8;
367
368         dst[i] = a << 24 | r << 16 | g << 8 | b;
369     }
370 }
371
372 static void
373 walk_region_internal (pixman_implementation_t *imp,
374                       pixman_op_t              op,
375                       pixman_image_t *         src_image,
376                       pixman_image_t *         mask_image,
377                       pixman_image_t *         dst_image,
378                       int32_t                  src_x,
379                       int32_t                  src_y,
380                       int32_t                  mask_x,
381                       int32_t                  mask_y,
382                       int32_t                  dest_x,
383                       int32_t                  dest_y,
384                       int32_t                  width,
385                       int32_t                  height,
386                       pixman_bool_t            src_repeat,
387                       pixman_bool_t            mask_repeat,
388                       pixman_region32_t *      region,
389                       pixman_composite_func_t  composite_rect)
390 {
391     int n;
392     const pixman_box32_t *pbox;
393     int w, h, w_this, h_this;
394     int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
395
396     pbox = pixman_region32_rectangles (region, &n);
397     while (n--)
398     {
399         h = pbox->y2 - pbox->y1;
400         y_src = pbox->y1 - dest_y + src_y;
401         y_msk = pbox->y1 - dest_y + mask_y;
402         y_dst = pbox->y1;
403
404         while (h)
405         {
406             h_this = h;
407             w = pbox->x2 - pbox->x1;
408             x_src = pbox->x1 - dest_x + src_x;
409             x_msk = pbox->x1 - dest_x + mask_x;
410             x_dst = pbox->x1;
411
412             if (mask_repeat)
413             {
414                 y_msk = MOD (y_msk, mask_image->bits.height);
415                 if (h_this > mask_image->bits.height - y_msk)
416                     h_this = mask_image->bits.height - y_msk;
417             }
418
419             if (src_repeat)
420             {
421                 y_src = MOD (y_src, src_image->bits.height);
422                 if (h_this > src_image->bits.height - y_src)
423                     h_this = src_image->bits.height - y_src;
424             }
425
426             while (w)
427             {
428                 w_this = w;
429
430                 if (mask_repeat)
431                 {
432                     x_msk = MOD (x_msk, mask_image->bits.width);
433                     if (w_this > mask_image->bits.width - x_msk)
434                         w_this = mask_image->bits.width - x_msk;
435                 }
436
437                 if (src_repeat)
438                 {
439                     x_src = MOD (x_src, src_image->bits.width);
440                     if (w_this > src_image->bits.width - x_src)
441                         w_this = src_image->bits.width - x_src;
442                 }
443
444                 (*composite_rect) (imp, op,
445                                    src_image, mask_image, dst_image,
446                                    x_src, y_src, x_msk, y_msk, x_dst, y_dst,
447                                    w_this, h_this);
448                 w -= w_this;
449
450                 x_src += w_this;
451                 x_msk += w_this;
452                 x_dst += w_this;
453             }
454
455             h -= h_this;
456             y_src += h_this;
457             y_msk += h_this;
458             y_dst += h_this;
459         }
460
461         pbox++;
462     }
463 }
464
465 void
466 _pixman_walk_composite_region (pixman_implementation_t *imp,
467                                pixman_op_t              op,
468                                pixman_image_t *         src_image,
469                                pixman_image_t *         mask_image,
470                                pixman_image_t *         dst_image,
471                                int32_t                  src_x,
472                                int32_t                  src_y,
473                                int32_t                  mask_x,
474                                int32_t                  mask_y,
475                                int32_t                  dest_x,
476                                int32_t                  dest_y,
477                                int32_t                  width,
478                                int32_t                  height,
479                                pixman_composite_func_t  composite_rect)
480 {
481     pixman_region32_t region;
482
483     pixman_region32_init (&region);
484
485     if (pixman_compute_composite_region32 (
486             &region, src_image, mask_image, dst_image,
487             src_x, src_y, mask_x, mask_y, dest_x, dest_y,
488             width, height))
489     {
490         walk_region_internal (imp, op,
491                               src_image, mask_image, dst_image,
492                               src_x, src_y, mask_x, mask_y, dest_x, dest_y,
493                               width, height, FALSE, FALSE,
494                               &region,
495                               composite_rect);
496
497         pixman_region32_fini (&region);
498     }
499 }
500
501 static pixman_bool_t
502 source_is_fastpathable (pixman_image_t *image)
503 {
504     if (image->common.transform                                 ||
505         image->common.alpha_map                                 ||
506         image->common.filter == PIXMAN_FILTER_CONVOLUTION       ||
507         image->common.repeat == PIXMAN_REPEAT_PAD               ||
508         image->common.repeat == PIXMAN_REPEAT_REFLECT)
509     {
510         return FALSE;
511     }
512
513     if (image->type == BITS                                     &&
514         (image->bits.read_func                                  ||
515          image->bits.write_func                                 ||
516          PIXMAN_FORMAT_IS_WIDE (image->bits.format)))
517     {
518         return FALSE;
519     }
520
521     return TRUE;
522 }
523
524 static pixman_bool_t
525 get_source_format_code (pixman_image_t *image, pixman_format_code_t *code)
526 {
527     if (!image)
528     {
529         *code = PIXMAN_null;
530         
531         return TRUE;
532     }
533     else
534     {
535         if (!source_is_fastpathable (image))
536             return FALSE;
537         
538         if (image->common.component_alpha)
539         {
540             if (image->type == BITS)
541             {
542                 /* These are the *only* component_alpha formats
543                  * we support for fast paths
544                  */
545                 if (image->bits.format == PIXMAN_a8r8g8b8)
546                     *code = PIXMAN_a8r8g8b8_ca;
547                 else if (image->bits.format == PIXMAN_a8b8g8r8)
548                     *code = PIXMAN_a8b8g8r8_ca;
549                 else
550                     return FALSE;
551             }
552             else
553             {
554                 return FALSE;
555             }
556         }
557         else if (_pixman_image_is_solid (image))
558         {
559             *code = PIXMAN_solid;
560         }
561         else if (image->common.type == BITS)
562         {
563             *code = image->bits.format;
564         }
565         else
566         {
567             return FALSE;
568         }
569         
570         return TRUE;
571     }
572 }
573
574 static force_inline pixman_bool_t
575 image_covers (pixman_image_t *image,
576               pixman_box32_t *extents,
577               int             x,
578               int             y)
579 {
580     if (image->common.type == BITS &&
581         image->common.repeat == PIXMAN_REPEAT_NONE)
582     {
583         if (x > extents->x1 || y > extents->y1 ||
584             x + image->bits.width < extents->x2 ||
585             y + image->bits.height < extents->y2)
586         {
587             return FALSE;
588         }
589     }
590
591     return TRUE;
592 }
593
594 static force_inline pixman_bool_t
595 sources_cover (pixman_image_t *src,
596                pixman_image_t *mask,
597                pixman_box32_t *extents,
598                int             src_x,
599                int             src_y,
600                int             mask_x,
601                int             mask_y,
602                int             dest_x,
603                int             dest_y)
604 {
605     if (!image_covers (src, extents, dest_x - src_x, dest_y - src_y))
606         return FALSE;
607
608     if (!mask)
609         return TRUE;
610
611     if (!image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
612         return FALSE;
613
614     return TRUE;
615 }
616
617 pixman_bool_t
618 _pixman_run_fast_path (const pixman_fast_path_t *paths,
619                        pixman_implementation_t * imp,
620                        pixman_op_t               op,
621                        pixman_image_t *          src,
622                        pixman_image_t *          mask,
623                        pixman_image_t *          dest,
624                        int32_t                   src_x,
625                        int32_t                   src_y,
626                        int32_t                   mask_x,
627                        int32_t                   mask_y,
628                        int32_t                   dest_x,
629                        int32_t                   dest_y,
630                        int32_t                   width,
631                        int32_t                   height)
632 {
633     pixman_bool_t src_repeat = src->common.repeat == PIXMAN_REPEAT_NORMAL;
634     pixman_bool_t mask_repeat = mask && mask->common.repeat == PIXMAN_REPEAT_NORMAL;
635     pixman_format_code_t src_format, mask_format, dest_format;
636     pixman_composite_func_t func = NULL;
637     const pixman_fast_path_t *info;
638     pixman_bool_t result;
639
640     if (!get_source_format_code (src, &src_format))
641         return FALSE;
642
643     if (!get_source_format_code (mask, &mask_format))
644         return FALSE;
645
646     if (dest->common.alpha_map  ||
647         dest->bits.read_func    ||
648         dest->bits.write_func)
649     {
650         return FALSE;
651     }
652
653     dest_format = dest->bits.format;
654
655     /* Check for pixbufs */
656     if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
657         (src->type == BITS && src->bits.bits == mask->bits.bits)           &&
658         (src->common.repeat == mask->common.repeat)                        &&
659         (src_x == mask_x && src_y == mask_y))
660     {
661         if (src_format == PIXMAN_x8b8g8r8)
662             src_format = mask_format = PIXMAN_pixbuf;
663         else if (src_format == PIXMAN_x8r8g8b8)
664             src_format = mask_format = PIXMAN_rpixbuf;
665     }
666
667     for (info = paths; info->op != PIXMAN_OP_NONE; ++info)
668     {
669         if (info->op == op                      &&
670             info->src_format == src_format      &&
671             info->mask_format == mask_format    &&
672             info->dest_format == dest_format)
673         {
674             func = info->func;
675             
676             if (info->src_format == PIXMAN_solid)
677                 src_repeat = FALSE;
678             
679             if (info->mask_format == PIXMAN_solid)
680                 mask_repeat = FALSE;
681             
682             if ((src_repeat                             &&
683                  src->bits.width == 1           &&
684                  src->bits.height == 1)         ||
685                 (mask_repeat                    &&
686                  mask->bits.width == 1          &&
687                  mask->bits.height == 1))
688             {
689                 /* If src or mask are repeating 1x1 images and src_repeat or
690                  * mask_repeat are still TRUE, it means the fast path we
691                  * selected does not actually handle repeating images.
692                  *
693                  * So rather than calling the "fast path" with a zillion
694                  * 1x1 requests, we just fall back to the general code (which
695                  * does do something sensible with 1x1 repeating images).
696                  */
697                 func = NULL;
698             }
699             break;
700         }
701     }
702
703     result = FALSE;
704     
705     if (func)
706     {
707         pixman_region32_t region;
708         pixman_region32_init (&region);
709
710         if (pixman_compute_composite_region32 (
711                 &region, src, mask, dest,
712                 src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
713         {
714             pixman_box32_t *extents = pixman_region32_extents (&region);
715
716             if (sources_cover (
717                     src, mask, extents,
718                     src_x, src_y, mask_x, mask_y, dest_x, dest_y))
719             {
720                 walk_region_internal (imp, op,
721                                       src, mask, dest,
722                                       src_x, src_y, mask_x, mask_y,
723                                       dest_x, dest_y,
724                                       width, height,
725                                       src_repeat, mask_repeat,
726                                       &region,
727                                       func);
728
729                 result = TRUE;
730             }
731
732             pixman_region32_fini (&region);
733         }
734     }
735
736     return result;
737 }
738
739 #define N_TMP_BOXES (16)
740
741 pixman_bool_t
742 pixman_region16_copy_from_region32 (pixman_region16_t *dst,
743                                     pixman_region32_t *src)
744 {
745     int n_boxes, i;
746     pixman_box32_t *boxes32;
747     pixman_box16_t *boxes16;
748     pixman_bool_t retval;
749
750     boxes32 = pixman_region32_rectangles (src, &n_boxes);
751
752     boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t));
753
754     if (!boxes16)
755         return FALSE;
756
757     for (i = 0; i < n_boxes; ++i)
758     {
759         boxes16[i].x1 = boxes32[i].x1;
760         boxes16[i].y1 = boxes32[i].y1;
761         boxes16[i].x2 = boxes32[i].x2;
762         boxes16[i].y2 = boxes32[i].y2;
763     }
764
765     pixman_region_fini (dst);
766     retval = pixman_region_init_rects (dst, boxes16, n_boxes);
767     free (boxes16);
768     return retval;
769 }
770
771 pixman_bool_t
772 pixman_region32_copy_from_region16 (pixman_region32_t *dst,
773                                     pixman_region16_t *src)
774 {
775     int n_boxes, i;
776     pixman_box16_t *boxes16;
777     pixman_box32_t *boxes32;
778     pixman_box32_t tmp_boxes[N_TMP_BOXES];
779     pixman_bool_t retval;
780
781     boxes16 = pixman_region_rectangles (src, &n_boxes);
782
783     if (n_boxes > N_TMP_BOXES)
784         boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t));
785     else
786         boxes32 = tmp_boxes;
787
788     if (!boxes32)
789         return FALSE;
790
791     for (i = 0; i < n_boxes; ++i)
792     {
793         boxes32[i].x1 = boxes16[i].x1;
794         boxes32[i].y1 = boxes16[i].y1;
795         boxes32[i].x2 = boxes16[i].x2;
796         boxes32[i].y2 = boxes16[i].y2;
797     }
798
799     pixman_region32_fini (dst);
800     retval = pixman_region32_init_rects (dst, boxes32, n_boxes);
801
802     if (boxes32 != tmp_boxes)
803         free (boxes32);
804
805     return retval;
806 }