|
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 #include <limits.h> |
|
31 |
|
32 #include "pixman-private.h" |
|
33 |
|
34 pixman_bool_t |
|
35 _pixman_multiply_overflows_size (size_t a, size_t b) |
|
36 { |
|
37 return a >= SIZE_MAX / b; |
|
38 } |
|
39 |
|
40 pixman_bool_t |
|
41 _pixman_multiply_overflows_int (unsigned int a, unsigned int b) |
|
42 { |
|
43 return a >= INT32_MAX / b; |
|
44 } |
|
45 |
|
46 pixman_bool_t |
|
47 _pixman_addition_overflows_int (unsigned int a, unsigned int b) |
|
48 { |
|
49 return a > INT32_MAX - b; |
|
50 } |
|
51 |
|
52 void * |
|
53 pixman_malloc_ab (unsigned int a, |
|
54 unsigned int b) |
|
55 { |
|
56 if (a >= INT32_MAX / b) |
|
57 return NULL; |
|
58 |
|
59 return malloc (a * b); |
|
60 } |
|
61 |
|
62 void * |
|
63 pixman_malloc_abc (unsigned int a, |
|
64 unsigned int b, |
|
65 unsigned int c) |
|
66 { |
|
67 if (a >= INT32_MAX / b) |
|
68 return NULL; |
|
69 else if (a * b >= INT32_MAX / c) |
|
70 return NULL; |
|
71 else |
|
72 return malloc (a * b * c); |
|
73 } |
|
74 |
|
75 static force_inline uint16_t |
|
76 float_to_unorm (float f, int n_bits) |
|
77 { |
|
78 uint32_t u; |
|
79 |
|
80 if (f > 1.0) |
|
81 f = 1.0; |
|
82 if (f < 0.0) |
|
83 f = 0.0; |
|
84 |
|
85 u = f * (1 << n_bits); |
|
86 u -= (u >> n_bits); |
|
87 |
|
88 return u; |
|
89 } |
|
90 |
|
91 static force_inline float |
|
92 unorm_to_float (uint16_t u, int n_bits) |
|
93 { |
|
94 uint32_t m = ((1 << n_bits) - 1); |
|
95 |
|
96 return (u & m) * (1.f / (float)m); |
|
97 } |
|
98 |
|
99 /* |
|
100 * This function expands images from a8r8g8b8 to argb_t. To preserve |
|
101 * precision, it needs to know from which source format the a8r8g8b8 pixels |
|
102 * originally came. |
|
103 * |
|
104 * For example, if the source was PIXMAN_x1r5g5b5 and the red component |
|
105 * contained bits 12345, then the 8-bit value is 12345123. To correctly |
|
106 * expand this to floating point, it should be 12345 / 31.0 and not |
|
107 * 12345123 / 255.0. |
|
108 */ |
|
109 void |
|
110 pixman_expand_to_float (argb_t *dst, |
|
111 const uint32_t *src, |
|
112 pixman_format_code_t format, |
|
113 int width) |
|
114 { |
|
115 static const float multipliers[16] = { |
|
116 0.0f, |
|
117 1.0f / ((1 << 1) - 1), |
|
118 1.0f / ((1 << 2) - 1), |
|
119 1.0f / ((1 << 3) - 1), |
|
120 1.0f / ((1 << 4) - 1), |
|
121 1.0f / ((1 << 5) - 1), |
|
122 1.0f / ((1 << 6) - 1), |
|
123 1.0f / ((1 << 7) - 1), |
|
124 1.0f / ((1 << 8) - 1), |
|
125 1.0f / ((1 << 9) - 1), |
|
126 1.0f / ((1 << 10) - 1), |
|
127 1.0f / ((1 << 11) - 1), |
|
128 1.0f / ((1 << 12) - 1), |
|
129 1.0f / ((1 << 13) - 1), |
|
130 1.0f / ((1 << 14) - 1), |
|
131 1.0f / ((1 << 15) - 1), |
|
132 }; |
|
133 int a_size, r_size, g_size, b_size; |
|
134 int a_shift, r_shift, g_shift, b_shift; |
|
135 float a_mul, r_mul, g_mul, b_mul; |
|
136 uint32_t a_mask, r_mask, g_mask, b_mask; |
|
137 int i; |
|
138 |
|
139 if (!PIXMAN_FORMAT_VIS (format)) |
|
140 format = PIXMAN_a8r8g8b8; |
|
141 |
|
142 /* |
|
143 * Determine the sizes of each component and the masks and shifts |
|
144 * required to extract them from the source pixel. |
|
145 */ |
|
146 a_size = PIXMAN_FORMAT_A (format); |
|
147 r_size = PIXMAN_FORMAT_R (format); |
|
148 g_size = PIXMAN_FORMAT_G (format); |
|
149 b_size = PIXMAN_FORMAT_B (format); |
|
150 |
|
151 a_shift = 32 - a_size; |
|
152 r_shift = 24 - r_size; |
|
153 g_shift = 16 - g_size; |
|
154 b_shift = 8 - b_size; |
|
155 |
|
156 a_mask = ((1 << a_size) - 1); |
|
157 r_mask = ((1 << r_size) - 1); |
|
158 g_mask = ((1 << g_size) - 1); |
|
159 b_mask = ((1 << b_size) - 1); |
|
160 |
|
161 a_mul = multipliers[a_size]; |
|
162 r_mul = multipliers[r_size]; |
|
163 g_mul = multipliers[g_size]; |
|
164 b_mul = multipliers[b_size]; |
|
165 |
|
166 /* Start at the end so that we can do the expansion in place |
|
167 * when src == dst |
|
168 */ |
|
169 for (i = width - 1; i >= 0; i--) |
|
170 { |
|
171 const uint32_t pixel = src[i]; |
|
172 |
|
173 dst[i].a = a_mask? ((pixel >> a_shift) & a_mask) * a_mul : 1.0f; |
|
174 dst[i].r = ((pixel >> r_shift) & r_mask) * r_mul; |
|
175 dst[i].g = ((pixel >> g_shift) & g_mask) * g_mul; |
|
176 dst[i].b = ((pixel >> b_shift) & b_mask) * b_mul; |
|
177 } |
|
178 } |
|
179 |
|
180 uint16_t |
|
181 pixman_float_to_unorm (float f, int n_bits) |
|
182 { |
|
183 return float_to_unorm (f, n_bits); |
|
184 } |
|
185 |
|
186 float |
|
187 pixman_unorm_to_float (uint16_t u, int n_bits) |
|
188 { |
|
189 return unorm_to_float (u, n_bits); |
|
190 } |
|
191 |
|
192 void |
|
193 pixman_contract_from_float (uint32_t *dst, |
|
194 const argb_t *src, |
|
195 int width) |
|
196 { |
|
197 int i; |
|
198 |
|
199 for (i = 0; i < width; ++i) |
|
200 { |
|
201 uint8_t a, r, g, b; |
|
202 |
|
203 a = float_to_unorm (src[i].a, 8); |
|
204 r = float_to_unorm (src[i].r, 8); |
|
205 g = float_to_unorm (src[i].g, 8); |
|
206 b = float_to_unorm (src[i].b, 8); |
|
207 |
|
208 dst[i] = (a << 24) | (r << 16) | (g << 8) | (b << 0); |
|
209 } |
|
210 } |
|
211 |
|
212 uint32_t * |
|
213 _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask) |
|
214 { |
|
215 return iter->buffer; |
|
216 } |
|
217 |
|
218 #define N_TMP_BOXES (16) |
|
219 |
|
220 pixman_bool_t |
|
221 pixman_region16_copy_from_region32 (pixman_region16_t *dst, |
|
222 pixman_region32_t *src) |
|
223 { |
|
224 int n_boxes, i; |
|
225 pixman_box32_t *boxes32; |
|
226 pixman_box16_t *boxes16; |
|
227 pixman_bool_t retval; |
|
228 |
|
229 boxes32 = pixman_region32_rectangles (src, &n_boxes); |
|
230 |
|
231 boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t)); |
|
232 |
|
233 if (!boxes16) |
|
234 return FALSE; |
|
235 |
|
236 for (i = 0; i < n_boxes; ++i) |
|
237 { |
|
238 boxes16[i].x1 = boxes32[i].x1; |
|
239 boxes16[i].y1 = boxes32[i].y1; |
|
240 boxes16[i].x2 = boxes32[i].x2; |
|
241 boxes16[i].y2 = boxes32[i].y2; |
|
242 } |
|
243 |
|
244 pixman_region_fini (dst); |
|
245 retval = pixman_region_init_rects (dst, boxes16, n_boxes); |
|
246 free (boxes16); |
|
247 return retval; |
|
248 } |
|
249 |
|
250 pixman_bool_t |
|
251 pixman_region32_copy_from_region16 (pixman_region32_t *dst, |
|
252 pixman_region16_t *src) |
|
253 { |
|
254 int n_boxes, i; |
|
255 pixman_box16_t *boxes16; |
|
256 pixman_box32_t *boxes32; |
|
257 pixman_box32_t tmp_boxes[N_TMP_BOXES]; |
|
258 pixman_bool_t retval; |
|
259 |
|
260 boxes16 = pixman_region_rectangles (src, &n_boxes); |
|
261 |
|
262 if (n_boxes > N_TMP_BOXES) |
|
263 boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t)); |
|
264 else |
|
265 boxes32 = tmp_boxes; |
|
266 |
|
267 if (!boxes32) |
|
268 return FALSE; |
|
269 |
|
270 for (i = 0; i < n_boxes; ++i) |
|
271 { |
|
272 boxes32[i].x1 = boxes16[i].x1; |
|
273 boxes32[i].y1 = boxes16[i].y1; |
|
274 boxes32[i].x2 = boxes16[i].x2; |
|
275 boxes32[i].y2 = boxes16[i].y2; |
|
276 } |
|
277 |
|
278 pixman_region32_fini (dst); |
|
279 retval = pixman_region32_init_rects (dst, boxes32, n_boxes); |
|
280 |
|
281 if (boxes32 != tmp_boxes) |
|
282 free (boxes32); |
|
283 |
|
284 return retval; |
|
285 } |
|
286 |
|
287 /* This function is exported for the sake of the test suite and not part |
|
288 * of the ABI. |
|
289 */ |
|
290 PIXMAN_EXPORT pixman_implementation_t * |
|
291 _pixman_internal_only_get_implementation (void) |
|
292 { |
|
293 return get_implementation (); |
|
294 } |
|
295 |
|
296 #ifdef DEBUG |
|
297 |
|
298 void |
|
299 _pixman_log_error (const char *function, const char *message) |
|
300 { |
|
301 static int n_messages = 0; |
|
302 |
|
303 if (n_messages < 10) |
|
304 { |
|
305 fprintf (stderr, |
|
306 "*** BUG ***\n" |
|
307 "In %s: %s\n" |
|
308 "Set a breakpoint on '_pixman_log_error' to debug\n\n", |
|
309 function, message); |
|
310 |
|
311 n_messages++; |
|
312 } |
|
313 } |
|
314 |
|
315 #endif |