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