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