Move iterator initialization to the respective image files
[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 pixman_bool_t
34 pixman_multiply_overflows_int (unsigned int a,
35                                unsigned int b)
36 {
37     return a >= INT32_MAX / b;
38 }
39
40 pixman_bool_t
41 pixman_addition_overflows_int (unsigned int a,
42                                unsigned int b)
43 {
44     return a > INT32_MAX - b;
45 }
46
47 void *
48 pixman_malloc_ab (unsigned int a,
49                   unsigned int b)
50 {
51     if (a >= INT32_MAX / b)
52         return NULL;
53
54     return malloc (a * b);
55 }
56
57 void *
58 pixman_malloc_abc (unsigned int a,
59                    unsigned int b,
60                    unsigned int c)
61 {
62     if (a >= INT32_MAX / b)
63         return NULL;
64     else if (a * b >= INT32_MAX / c)
65         return NULL;
66     else
67         return malloc (a * b * c);
68 }
69
70 /*
71  * Helper routine to expand a color component from 0 < n <= 8 bits to 16
72  * bits by replication.
73  */
74 static inline uint64_t
75 expand16 (const uint8_t val, int nbits)
76 {
77     /* Start out with the high bit of val in the high bit of result. */
78     uint16_t result = (uint16_t)val << (16 - nbits);
79
80     if (nbits == 0)
81         return 0;
82
83     /* Copy the bits in result, doubling the number of bits each time, until
84      * we fill all 16 bits.
85      */
86     while (nbits < 16)
87     {
88         result |= result >> nbits;
89         nbits *= 2;
90     }
91
92     return result;
93 }
94
95 /*
96  * This function expands images from ARGB8 format to ARGB16.  To preserve
97  * precision, it needs to know the original source format.  For example, if the
98  * source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then
99  * the expanded value is 12345123.  To correctly expand this to 16 bits, it
100  * should be 1234512345123451 and not 1234512312345123.
101  */
102 void
103 pixman_expand (uint64_t *           dst,
104                const uint32_t *     src,
105                pixman_format_code_t format,
106                int                  width)
107 {
108     /*
109      * Determine the sizes of each component and the masks and shifts
110      * required to extract them from the source pixel.
111      */
112     const int a_size = PIXMAN_FORMAT_A (format),
113               r_size = PIXMAN_FORMAT_R (format),
114               g_size = PIXMAN_FORMAT_G (format),
115               b_size = PIXMAN_FORMAT_B (format);
116     const int a_shift = 32 - a_size,
117               r_shift = 24 - r_size,
118               g_shift = 16 - g_size,
119               b_shift =  8 - b_size;
120     const uint8_t a_mask = ~(~0 << a_size),
121                   r_mask = ~(~0 << r_size),
122                   g_mask = ~(~0 << g_size),
123                   b_mask = ~(~0 << b_size);
124     int i;
125
126     /* Start at the end so that we can do the expansion in place
127      * when src == dst
128      */
129     for (i = width - 1; i >= 0; i--)
130     {
131         const uint32_t pixel = src[i];
132         const uint8_t a = (pixel >> a_shift) & a_mask,
133                       r = (pixel >> r_shift) & r_mask,
134                       g = (pixel >> g_shift) & g_mask,
135                       b = (pixel >> b_shift) & b_mask;
136         const uint64_t a16 = a_size ? expand16 (a, a_size) : 0xffff,
137                        r16 = expand16 (r, r_size),
138                        g16 = expand16 (g, g_size),
139                        b16 = expand16 (b, b_size);
140
141         dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16;
142     }
143 }
144
145 /*
146  * Contracting is easier than expanding.  We just need to truncate the
147  * components.
148  */
149 void
150 pixman_contract (uint32_t *      dst,
151                  const uint64_t *src,
152                  int             width)
153 {
154     int i;
155
156     /* Start at the beginning so that we can do the contraction in
157      * place when src == dst
158      */
159     for (i = 0; i < width; i++)
160     {
161         const uint8_t a = src[i] >> 56,
162                       r = src[i] >> 40,
163                       g = src[i] >> 24,
164                       b = src[i] >> 8;
165
166         dst[i] = a << 24 | r << 16 | g << 8 | b;
167     }
168 }
169
170 uint32_t *
171 _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask)
172 {
173     return iter->buffer;
174 }
175
176 #define N_TMP_BOXES (16)
177
178 pixman_bool_t
179 pixman_region16_copy_from_region32 (pixman_region16_t *dst,
180                                     pixman_region32_t *src)
181 {
182     int n_boxes, i;
183     pixman_box32_t *boxes32;
184     pixman_box16_t *boxes16;
185     pixman_bool_t retval;
186
187     boxes32 = pixman_region32_rectangles (src, &n_boxes);
188
189     boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t));
190
191     if (!boxes16)
192         return FALSE;
193
194     for (i = 0; i < n_boxes; ++i)
195     {
196         boxes16[i].x1 = boxes32[i].x1;
197         boxes16[i].y1 = boxes32[i].y1;
198         boxes16[i].x2 = boxes32[i].x2;
199         boxes16[i].y2 = boxes32[i].y2;
200     }
201
202     pixman_region_fini (dst);
203     retval = pixman_region_init_rects (dst, boxes16, n_boxes);
204     free (boxes16);
205     return retval;
206 }
207
208 pixman_bool_t
209 pixman_region32_copy_from_region16 (pixman_region32_t *dst,
210                                     pixman_region16_t *src)
211 {
212     int n_boxes, i;
213     pixman_box16_t *boxes16;
214     pixman_box32_t *boxes32;
215     pixman_box32_t tmp_boxes[N_TMP_BOXES];
216     pixman_bool_t retval;
217
218     boxes16 = pixman_region_rectangles (src, &n_boxes);
219
220     if (n_boxes > N_TMP_BOXES)
221         boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t));
222     else
223         boxes32 = tmp_boxes;
224
225     if (!boxes32)
226         return FALSE;
227
228     for (i = 0; i < n_boxes; ++i)
229     {
230         boxes32[i].x1 = boxes16[i].x1;
231         boxes32[i].y1 = boxes16[i].y1;
232         boxes32[i].x2 = boxes16[i].x2;
233         boxes32[i].y2 = boxes16[i].y2;
234     }
235
236     pixman_region32_fini (dst);
237     retval = pixman_region32_init_rects (dst, boxes32, n_boxes);
238
239     if (boxes32 != tmp_boxes)
240         free (boxes32);
241
242     return retval;
243 }
244
245 #ifdef DEBUG
246
247 void
248 _pixman_log_error (const char *function, const char *message)
249 {
250     static int n_messages = 0;
251
252     if (n_messages < 10)
253     {
254         fprintf (stderr,
255                  "*** BUG ***\n"
256                  "In %s: %s\n"
257                  "Set a breakpoint on '_pixman_log_error' to debug\n\n",
258                  function, message);
259
260         n_messages++;
261     }
262 }
263
264 #endif