Eliminate the NEED_COMPONENT_ALPHA flag.
[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 const pixman_fast_path_t *
502 get_fast_path (const pixman_fast_path_t *fast_paths,
503                pixman_op_t               op,
504                pixman_image_t *          src_image,
505                pixman_image_t *          mask_image,
506                pixman_image_t *          dst_image,
507                pixman_bool_t             is_pixbuf)
508 {
509     const pixman_fast_path_t *info;
510
511     pixman_format_code_t mask_format;
512
513     if (!mask_image)
514     {
515         mask_format = PIXMAN_null;
516     }
517     else if (mask_image->common.component_alpha)
518     {
519         if (mask_image->type == BITS)
520         {
521             /* These are the *only* component_alpha formats
522              * we support for fast paths
523              */
524             if (mask_image->bits.format == PIXMAN_a8r8g8b8)
525                 mask_format = PIXMAN_a8r8g8b8_ca;
526             else if (mask_image->bits.format == PIXMAN_a8b8g8r8)
527                 mask_format = PIXMAN_a8b8g8r8_ca;
528             else
529                 return NULL;
530         }
531         else
532         {
533             return NULL;
534         }
535     }
536     else if (_pixman_image_is_solid (mask_image))
537     {
538         mask_format = PIXMAN_solid;
539     }
540     else if (mask_image->common.type == BITS)
541     {
542         mask_format = mask_image->bits.format;
543     }
544     else
545     {
546         return NULL;
547     }
548     
549     for (info = fast_paths; info->op != PIXMAN_OP_NONE; info++)
550     {
551         pixman_bool_t valid_src = FALSE;
552
553         if (info->op != op)
554             continue;
555
556         if ((info->src_format == PIXMAN_solid &&
557              _pixman_image_is_solid (src_image)) ||
558             (src_image->type == BITS &&
559              info->src_format == src_image->bits.format))
560         {
561             valid_src = TRUE;
562         }
563
564         if (!valid_src)
565             continue;
566
567         if (info->mask_format != mask_format)
568             continue;
569
570         if (info->dest_format != dst_image->bits.format)
571             continue;
572
573         if ((info->flags & NEED_PIXBUF) && !is_pixbuf)
574             continue;
575
576         return info;
577     }
578
579     return NULL;
580 }
581
582 static force_inline pixman_bool_t
583 image_covers (pixman_image_t *image,
584               pixman_box32_t *extents,
585               int             x,
586               int             y)
587 {
588     if (image->common.type == BITS &&
589         image->common.repeat == PIXMAN_REPEAT_NONE)
590     {
591         if (x > extents->x1 || y > extents->y1 ||
592             x + image->bits.width < extents->x2 ||
593             y + image->bits.height < extents->y2)
594         {
595             return FALSE;
596         }
597     }
598
599     return TRUE;
600 }
601
602 static force_inline pixman_bool_t
603 sources_cover (pixman_image_t *src,
604                pixman_image_t *mask,
605                pixman_box32_t *extents,
606                int             src_x,
607                int             src_y,
608                int             mask_x,
609                int             mask_y,
610                int             dest_x,
611                int             dest_y)
612 {
613     if (!image_covers (src, extents, dest_x - src_x, dest_y - src_y))
614         return FALSE;
615
616     if (!mask)
617         return TRUE;
618
619     if (!image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
620         return FALSE;
621
622     return TRUE;
623 }
624
625 pixman_bool_t
626 _pixman_run_fast_path (const pixman_fast_path_t *paths,
627                        pixman_implementation_t * imp,
628                        pixman_op_t               op,
629                        pixman_image_t *          src,
630                        pixman_image_t *          mask,
631                        pixman_image_t *          dest,
632                        int32_t                   src_x,
633                        int32_t                   src_y,
634                        int32_t                   mask_x,
635                        int32_t                   mask_y,
636                        int32_t                   dest_x,
637                        int32_t                   dest_y,
638                        int32_t                   width,
639                        int32_t                   height)
640 {
641     pixman_composite_func_t func = NULL;
642     pixman_bool_t src_repeat =
643         src->common.repeat == PIXMAN_REPEAT_NORMAL;
644     pixman_bool_t mask_repeat =
645         mask && mask->common.repeat == PIXMAN_REPEAT_NORMAL;
646     pixman_bool_t result;
647     pixman_bool_t has_fast_path;
648
649     has_fast_path = !dest->common.alpha_map &&
650                     !dest->bits.read_func &&
651                     !dest->bits.write_func;
652
653     if (has_fast_path)
654     {
655         has_fast_path = (src->type == BITS || _pixman_image_is_solid (src)) &&
656                         !src->common.transform &&
657                         !src->common.alpha_map &&
658                         src->common.filter != PIXMAN_FILTER_CONVOLUTION &&
659                         src->common.repeat != PIXMAN_REPEAT_PAD &&
660                         src->common.repeat != PIXMAN_REPEAT_REFLECT;
661         if (has_fast_path && src->type == BITS)
662         {
663             has_fast_path = !src->bits.read_func &&
664                             !src->bits.write_func &&
665                             !PIXMAN_FORMAT_IS_WIDE (src->bits.format);
666         }
667     }
668
669     if (mask && has_fast_path)
670     {
671         has_fast_path =
672             mask->type == BITS &&
673             !mask->common.transform &&
674             !mask->common.alpha_map &&
675             !mask->bits.read_func &&
676             !mask->bits.write_func &&
677             mask->common.filter != PIXMAN_FILTER_CONVOLUTION &&
678             mask->common.repeat != PIXMAN_REPEAT_PAD &&
679             mask->common.repeat != PIXMAN_REPEAT_REFLECT &&
680             !PIXMAN_FORMAT_IS_WIDE (mask->bits.format);
681     }
682
683     if (has_fast_path)
684     {
685         const pixman_fast_path_t *info;
686         pixman_bool_t pixbuf;
687
688         pixbuf =
689             src && src->type == BITS            &&
690             mask && mask->type == BITS          &&
691             src->bits.bits == mask->bits.bits   &&
692             src_x == mask_x                     &&
693             src_y == mask_y                     &&
694             !mask->common.component_alpha       &&
695             !mask_repeat;
696
697         info = get_fast_path (paths, op, src, mask, dest, pixbuf);
698
699         if (info)
700         {
701             func = info->func;
702
703             if (info->src_format == PIXMAN_solid)
704                 src_repeat = FALSE;
705
706             if (info->mask_format == PIXMAN_solid)
707             {
708                 mask_repeat = FALSE;
709             }
710
711             if ((src_repeat                     &&
712                  src->bits.width == 1           &&
713                  src->bits.height == 1) ||
714                 (mask_repeat                    &&
715                  mask->bits.width == 1          &&
716                  mask->bits.height == 1))
717             {
718                 /* If src or mask are repeating 1x1 images and src_repeat or
719                  * mask_repeat are still TRUE, it means the fast path we
720                  * selected does not actually handle repeating images.
721                  *
722                  * So rather than call the "fast path" with a zillion
723                  * 1x1 requests, we just fall back to the general code (which
724                  * does do something sensible with 1x1 repeating images).
725                  */
726                 func = NULL;
727             }
728         }
729     }
730
731     result = FALSE;
732
733     if (func)
734     {
735         pixman_region32_t region;
736         pixman_region32_init (&region);
737
738         if (pixman_compute_composite_region32 (
739                 &region, src, mask, dest,
740                 src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
741         {
742             pixman_box32_t *extents = pixman_region32_extents (&region);
743
744             if (sources_cover (
745                     src, mask, extents,
746                     src_x, src_y, mask_x, mask_y, dest_x, dest_y))
747             {
748                 walk_region_internal (imp, op,
749                                       src, mask, dest,
750                                       src_x, src_y, mask_x, mask_y,
751                                       dest_x, dest_y,
752                                       width, height,
753                                       src_repeat, mask_repeat,
754                                       &region,
755                                       func);
756
757                 result = TRUE;
758             }
759
760             pixman_region32_fini (&region);
761         }
762     }
763
764     return result;
765 }
766
767 #define N_TMP_BOXES (16)
768
769 pixman_bool_t
770 pixman_region16_copy_from_region32 (pixman_region16_t *dst,
771                                     pixman_region32_t *src)
772 {
773     int n_boxes, i;
774     pixman_box32_t *boxes32;
775     pixman_box16_t *boxes16;
776     pixman_bool_t retval;
777
778     boxes32 = pixman_region32_rectangles (src, &n_boxes);
779
780     boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t));
781
782     if (!boxes16)
783         return FALSE;
784
785     for (i = 0; i < n_boxes; ++i)
786     {
787         boxes16[i].x1 = boxes32[i].x1;
788         boxes16[i].y1 = boxes32[i].y1;
789         boxes16[i].x2 = boxes32[i].x2;
790         boxes16[i].y2 = boxes32[i].y2;
791     }
792
793     pixman_region_fini (dst);
794     retval = pixman_region_init_rects (dst, boxes16, n_boxes);
795     free (boxes16);
796     return retval;
797 }
798
799 pixman_bool_t
800 pixman_region32_copy_from_region16 (pixman_region32_t *dst,
801                                     pixman_region16_t *src)
802 {
803     int n_boxes, i;
804     pixman_box16_t *boxes16;
805     pixman_box32_t *boxes32;
806     pixman_box32_t tmp_boxes[N_TMP_BOXES];
807     pixman_bool_t retval;
808
809     boxes16 = pixman_region_rectangles (src, &n_boxes);
810
811     if (n_boxes > N_TMP_BOXES)
812         boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t));
813     else
814         boxes32 = tmp_boxes;
815
816     if (!boxes32)
817         return FALSE;
818
819     for (i = 0; i < n_boxes; ++i)
820     {
821         boxes32[i].x1 = boxes16[i].x1;
822         boxes32[i].y1 = boxes16[i].y1;
823         boxes32[i].x2 = boxes16[i].x2;
824         boxes32[i].y2 = boxes16[i].y2;
825     }
826
827     pixman_region32_fini (dst);
828     retval = pixman_region32_init_rects (dst, boxes32, n_boxes);
829
830     if (boxes32 != tmp_boxes)
831         free (boxes32);
832
833     return retval;
834 }