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