1b4b94579Smrg/*
2b4b94579Smrg * Copyright © 2000 SuSE, Inc.
3dc259aabSmrg * Copyright © 1999 Keith Packard
4b4b94579Smrg *
5b4b94579Smrg * Permission to use, copy, modify, distribute, and sell this software and its
6b4b94579Smrg * documentation for any purpose is hereby granted without fee, provided that
7b4b94579Smrg * the above copyright notice appear in all copies and that both that
8b4b94579Smrg * copyright notice and this permission notice appear in supporting
9b4b94579Smrg * documentation, and that the name of SuSE not be used in advertising or
10b4b94579Smrg * publicity pertaining to distribution of the software without specific,
11b4b94579Smrg * written prior permission.  SuSE makes no representations about the
12b4b94579Smrg * suitability of this software for any purpose.  It is provided "as is"
13b4b94579Smrg * without express or implied warranty.
14b4b94579Smrg *
15b4b94579Smrg * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
16b4b94579Smrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
17b4b94579Smrg * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18b4b94579Smrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19b4b94579Smrg * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20b4b94579Smrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21b4b94579Smrg *
22b4b94579Smrg * Author:  Keith Packard, SuSE, Inc.
23b4b94579Smrg */
24b4b94579Smrg
25b4b94579Smrg#ifdef HAVE_CONFIG_H
2614b11b2bSmrg#include <pixman-config.h>
27b4b94579Smrg#endif
28dc259aabSmrg#include <stdio.h>
29b4b94579Smrg#include <stdlib.h>
30b4b94579Smrg
31b4b94579Smrg#include "pixman-private.h"
32b4b94579Smrg
33b4b94579Smrgpixman_bool_t
349ad247e8Sjmcneill_pixman_multiply_overflows_size (size_t a, size_t b)
359ad247e8Sjmcneill{
369ad247e8Sjmcneill    return a >= SIZE_MAX / b;
379ad247e8Sjmcneill}
389ad247e8Sjmcneill
399ad247e8Sjmcneillpixman_bool_t
409ad247e8Sjmcneill_pixman_multiply_overflows_int (unsigned int a, unsigned int b)
41b4b94579Smrg{
42b4b94579Smrg    return a >= INT32_MAX / b;
43b4b94579Smrg}
44b4b94579Smrg
45b4b94579Smrgpixman_bool_t
469ad247e8Sjmcneill_pixman_addition_overflows_int (unsigned int a, unsigned int b)
47b4b94579Smrg{
48b4b94579Smrg    return a > INT32_MAX - b;
49b4b94579Smrg}
50b4b94579Smrg
51de17ff4aSmrgvoid *
52de17ff4aSmrgpixman_malloc_ab_plus_c (unsigned int a, unsigned int b, unsigned int c)
53de17ff4aSmrg{
54de17ff4aSmrg    if (!b || a >= INT32_MAX / b || (a * b) > INT32_MAX - c)
55de17ff4aSmrg	return NULL;
56de17ff4aSmrg
57de17ff4aSmrg    return malloc (a * b + c);
58de17ff4aSmrg}
59de17ff4aSmrg
60b4b94579Smrgvoid *
61d0321353Smrgpixman_malloc_ab (unsigned int a,
62d0321353Smrg                  unsigned int b)
63b4b94579Smrg{
64b4b94579Smrg    if (a >= INT32_MAX / b)
65b4b94579Smrg	return NULL;
66b4b94579Smrg
67b4b94579Smrg    return malloc (a * b);
68b4b94579Smrg}
69b4b94579Smrg
70b4b94579Smrgvoid *
71b4b94579Smrgpixman_malloc_abc (unsigned int a,
72d0321353Smrg                   unsigned int b,
73d0321353Smrg                   unsigned int c)
74b4b94579Smrg{
75b4b94579Smrg    if (a >= INT32_MAX / b)
76b4b94579Smrg	return NULL;
77b4b94579Smrg    else if (a * b >= INT32_MAX / c)
78b4b94579Smrg	return NULL;
79b4b94579Smrg    else
80b4b94579Smrg	return malloc (a * b * c);
81b4b94579Smrg}
82b4b94579Smrg
839ad247e8Sjmcneillstatic force_inline uint16_t
849ad247e8Sjmcneillfloat_to_unorm (float f, int n_bits)
85317c648bSmrg{
869ad247e8Sjmcneill    uint32_t u;
87317c648bSmrg
889ad247e8Sjmcneill    if (f > 1.0)
899ad247e8Sjmcneill	f = 1.0;
909ad247e8Sjmcneill    if (f < 0.0)
919ad247e8Sjmcneill	f = 0.0;
92317c648bSmrg
939ad247e8Sjmcneill    u = f * (1 << n_bits);
949ad247e8Sjmcneill    u -= (u >> n_bits);
95317c648bSmrg
969ad247e8Sjmcneill    return u;
979ad247e8Sjmcneill}
989ad247e8Sjmcneill
999ad247e8Sjmcneillstatic force_inline float
1009ad247e8Sjmcneillunorm_to_float (uint16_t u, int n_bits)
1019ad247e8Sjmcneill{
1029ad247e8Sjmcneill    uint32_t m = ((1 << n_bits) - 1);
1039ad247e8Sjmcneill
1049ad247e8Sjmcneill    return (u & m) * (1.f / (float)m);
105317c648bSmrg}
106317c648bSmrg
107317c648bSmrg/*
1089ad247e8Sjmcneill * This function expands images from a8r8g8b8 to argb_t.  To preserve
1099ad247e8Sjmcneill * precision, it needs to know from which source format the a8r8g8b8 pixels
1109ad247e8Sjmcneill * originally came.
1119ad247e8Sjmcneill *
1129ad247e8Sjmcneill * For example, if the source was PIXMAN_x1r5g5b5 and the red component
1139ad247e8Sjmcneill * contained bits 12345, then the 8-bit value is 12345123.  To correctly
1149ad247e8Sjmcneill * expand this to floating point, it should be 12345 / 31.0 and not
1159ad247e8Sjmcneill * 12345123 / 255.0.
116317c648bSmrg */
117317c648bSmrgvoid
1189ad247e8Sjmcneillpixman_expand_to_float (argb_t               *dst,
1199ad247e8Sjmcneill			const uint32_t       *src,
1209ad247e8Sjmcneill			pixman_format_code_t  format,
1219ad247e8Sjmcneill			int                   width)
122317c648bSmrg{
1239ad247e8Sjmcneill    static const float multipliers[16] = {
1249ad247e8Sjmcneill	0.0f,
1259ad247e8Sjmcneill	1.0f / ((1 <<  1) - 1),
1269ad247e8Sjmcneill	1.0f / ((1 <<  2) - 1),
1279ad247e8Sjmcneill	1.0f / ((1 <<  3) - 1),
1289ad247e8Sjmcneill	1.0f / ((1 <<  4) - 1),
1299ad247e8Sjmcneill	1.0f / ((1 <<  5) - 1),
1309ad247e8Sjmcneill	1.0f / ((1 <<  6) - 1),
1319ad247e8Sjmcneill	1.0f / ((1 <<  7) - 1),
1329ad247e8Sjmcneill	1.0f / ((1 <<  8) - 1),
1339ad247e8Sjmcneill	1.0f / ((1 <<  9) - 1),
1349ad247e8Sjmcneill	1.0f / ((1 << 10) - 1),
1359ad247e8Sjmcneill	1.0f / ((1 << 11) - 1),
1369ad247e8Sjmcneill	1.0f / ((1 << 12) - 1),
1379ad247e8Sjmcneill	1.0f / ((1 << 13) - 1),
1389ad247e8Sjmcneill	1.0f / ((1 << 14) - 1),
1399ad247e8Sjmcneill	1.0f / ((1 << 15) - 1),
1409ad247e8Sjmcneill    };
1419ad247e8Sjmcneill    int a_size, r_size, g_size, b_size;
1429ad247e8Sjmcneill    int a_shift, r_shift, g_shift, b_shift;
1439ad247e8Sjmcneill    float a_mul, r_mul, g_mul, b_mul;
1449ad247e8Sjmcneill    uint32_t a_mask, r_mask, g_mask, b_mask;
1459ad247e8Sjmcneill    int i;
1469ad247e8Sjmcneill
1479ad247e8Sjmcneill    if (!PIXMAN_FORMAT_VIS (format))
1489ad247e8Sjmcneill	format = PIXMAN_a8r8g8b8;
1499ad247e8Sjmcneill
150317c648bSmrg    /*
151d0321353Smrg     * Determine the sizes of each component and the masks and shifts
152d0321353Smrg     * required to extract them from the source pixel.
153317c648bSmrg     */
1549ad247e8Sjmcneill    a_size = PIXMAN_FORMAT_A (format);
1559ad247e8Sjmcneill    r_size = PIXMAN_FORMAT_R (format);
1569ad247e8Sjmcneill    g_size = PIXMAN_FORMAT_G (format);
1579ad247e8Sjmcneill    b_size = PIXMAN_FORMAT_B (format);
1589ad247e8Sjmcneill
1599ad247e8Sjmcneill    a_shift = 32 - a_size;
1609ad247e8Sjmcneill    r_shift = 24 - r_size;
1619ad247e8Sjmcneill    g_shift = 16 - g_size;
1629ad247e8Sjmcneill    b_shift =  8 - b_size;
1639ad247e8Sjmcneill
1649ad247e8Sjmcneill    a_mask = ((1 << a_size) - 1);
1659ad247e8Sjmcneill    r_mask = ((1 << r_size) - 1);
1669ad247e8Sjmcneill    g_mask = ((1 << g_size) - 1);
1679ad247e8Sjmcneill    b_mask = ((1 << b_size) - 1);
1689ad247e8Sjmcneill
1699ad247e8Sjmcneill    a_mul = multipliers[a_size];
1709ad247e8Sjmcneill    r_mul = multipliers[r_size];
1719ad247e8Sjmcneill    g_mul = multipliers[g_size];
1729ad247e8Sjmcneill    b_mul = multipliers[b_size];
173317c648bSmrg
174d0321353Smrg    /* Start at the end so that we can do the expansion in place
175d0321353Smrg     * when src == dst
176d0321353Smrg     */
177317c648bSmrg    for (i = width - 1; i >= 0; i--)
178317c648bSmrg    {
179d0321353Smrg	const uint32_t pixel = src[i];
1809ad247e8Sjmcneill
1819ad247e8Sjmcneill	dst[i].a = a_mask? ((pixel >> a_shift) & a_mask) * a_mul : 1.0f;
1829ad247e8Sjmcneill	dst[i].r = ((pixel >> r_shift) & r_mask) * r_mul;
1839ad247e8Sjmcneill	dst[i].g = ((pixel >> g_shift) & g_mask) * g_mul;
1849ad247e8Sjmcneill	dst[i].b = ((pixel >> b_shift) & b_mask) * b_mul;
185317c648bSmrg    }
186317c648bSmrg}
187317c648bSmrg
1889ad247e8Sjmcneilluint16_t
1899ad247e8Sjmcneillpixman_float_to_unorm (float f, int n_bits)
1909ad247e8Sjmcneill{
1919ad247e8Sjmcneill    return float_to_unorm (f, n_bits);
1929ad247e8Sjmcneill}
1939ad247e8Sjmcneill
1949ad247e8Sjmcneillfloat
1959ad247e8Sjmcneillpixman_unorm_to_float (uint16_t u, int n_bits)
1969ad247e8Sjmcneill{
1979ad247e8Sjmcneill    return unorm_to_float (u, n_bits);
1989ad247e8Sjmcneill}
1999ad247e8Sjmcneill
200317c648bSmrgvoid
2019ad247e8Sjmcneillpixman_contract_from_float (uint32_t     *dst,
2029ad247e8Sjmcneill			    const argb_t *src,
2039ad247e8Sjmcneill			    int           width)
204317c648bSmrg{
205317c648bSmrg    int i;
206317c648bSmrg
2079ad247e8Sjmcneill    for (i = 0; i < width; ++i)
208317c648bSmrg    {
20914b11b2bSmrg	uint32_t a, r, g, b;
2109ad247e8Sjmcneill
2119ad247e8Sjmcneill	a = float_to_unorm (src[i].a, 8);
2129ad247e8Sjmcneill	r = float_to_unorm (src[i].r, 8);
2139ad247e8Sjmcneill	g = float_to_unorm (src[i].g, 8);
2149ad247e8Sjmcneill	b = float_to_unorm (src[i].b, 8);
215d0321353Smrg
2169ad247e8Sjmcneill	dst[i] = (a << 24) | (r << 16) | (g << 8) | (b << 0);
217317c648bSmrg    }
218317c648bSmrg}
219317c648bSmrg
220953d7d37Smrguint32_t *
221953d7d37Smrg_pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask)
222953d7d37Smrg{
223953d7d37Smrg    return iter->buffer;
224953d7d37Smrg}
225953d7d37Smrg
226de17ff4aSmrgvoid
227de17ff4aSmrg_pixman_iter_init_bits_stride (pixman_iter_t *iter, const pixman_iter_info_t *info)
228de17ff4aSmrg{
229de17ff4aSmrg    pixman_image_t *image = iter->image;
230de17ff4aSmrg    uint8_t *b = (uint8_t *)image->bits.bits;
231de17ff4aSmrg    int s = image->bits.rowstride * 4;
232de17ff4aSmrg
233de17ff4aSmrg    iter->bits = b + s * iter->y + iter->x * PIXMAN_FORMAT_BPP (info->format) / 8;
234de17ff4aSmrg    iter->stride = s;
235de17ff4aSmrg}
236de17ff4aSmrg
237dc259aabSmrg#define N_TMP_BOXES (16)
238dc259aabSmrg
239dc259aabSmrgpixman_bool_t
240dc259aabSmrgpixman_region16_copy_from_region32 (pixman_region16_t *dst,
24114b11b2bSmrg                                    const pixman_region32_t *src)
242dc259aabSmrg{
243dc259aabSmrg    int n_boxes, i;
244dc259aabSmrg    pixman_box32_t *boxes32;
245dc259aabSmrg    pixman_box16_t *boxes16;
246dc259aabSmrg    pixman_bool_t retval;
247d0321353Smrg
248dc259aabSmrg    boxes32 = pixman_region32_rectangles (src, &n_boxes);
249dc259aabSmrg
250dc259aabSmrg    boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t));
251dc259aabSmrg
252dc259aabSmrg    if (!boxes16)
253dc259aabSmrg	return FALSE;
254d0321353Smrg
255dc259aabSmrg    for (i = 0; i < n_boxes; ++i)
256dc259aabSmrg    {
257dc259aabSmrg	boxes16[i].x1 = boxes32[i].x1;
258dc259aabSmrg	boxes16[i].y1 = boxes32[i].y1;
259dc259aabSmrg	boxes16[i].x2 = boxes32[i].x2;
260dc259aabSmrg	boxes16[i].y2 = boxes32[i].y2;
261dc259aabSmrg    }
262dc259aabSmrg
263dc259aabSmrg    pixman_region_fini (dst);
264dc259aabSmrg    retval = pixman_region_init_rects (dst, boxes16, n_boxes);
265dc259aabSmrg    free (boxes16);
266dc259aabSmrg    return retval;
267317c648bSmrg}
268dc259aabSmrg
269dc259aabSmrgpixman_bool_t
270dc259aabSmrgpixman_region32_copy_from_region16 (pixman_region32_t *dst,
27114b11b2bSmrg                                    const pixman_region16_t *src)
272dc259aabSmrg{
273dc259aabSmrg    int n_boxes, i;
274dc259aabSmrg    pixman_box16_t *boxes16;
275dc259aabSmrg    pixman_box32_t *boxes32;
276dc259aabSmrg    pixman_box32_t tmp_boxes[N_TMP_BOXES];
277dc259aabSmrg    pixman_bool_t retval;
278d0321353Smrg
279dc259aabSmrg    boxes16 = pixman_region_rectangles (src, &n_boxes);
280dc259aabSmrg
281dc259aabSmrg    if (n_boxes > N_TMP_BOXES)
282dc259aabSmrg	boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t));
283dc259aabSmrg    else
284dc259aabSmrg	boxes32 = tmp_boxes;
285d0321353Smrg
286dc259aabSmrg    if (!boxes32)
287dc259aabSmrg	return FALSE;
288d0321353Smrg
289dc259aabSmrg    for (i = 0; i < n_boxes; ++i)
290dc259aabSmrg    {
291dc259aabSmrg	boxes32[i].x1 = boxes16[i].x1;
292dc259aabSmrg	boxes32[i].y1 = boxes16[i].y1;
293dc259aabSmrg	boxes32[i].x2 = boxes16[i].x2;
294dc259aabSmrg	boxes32[i].y2 = boxes16[i].y2;
295dc259aabSmrg    }
296dc259aabSmrg
297dc259aabSmrg    pixman_region32_fini (dst);
298dc259aabSmrg    retval = pixman_region32_init_rects (dst, boxes32, n_boxes);
299dc259aabSmrg
300dc259aabSmrg    if (boxes32 != tmp_boxes)
301dc259aabSmrg	free (boxes32);
302dc259aabSmrg
303dc259aabSmrg    return retval;
304dc259aabSmrg}
305952204abSmrg
30614b11b2bSmrgpixman_bool_t
30714b11b2bSmrgpixman_region32_copy_from_region64f (pixman_region32_t *dst,
30814b11b2bSmrg                                     const pixman_region64f_t *src)
30914b11b2bSmrg{
31014b11b2bSmrg    int n_boxes, i;
31114b11b2bSmrg    pixman_box64f_t *boxes64f;
31214b11b2bSmrg    pixman_box32_t *boxes32;
31314b11b2bSmrg    pixman_box32_t tmp_boxes[N_TMP_BOXES];
31414b11b2bSmrg    pixman_bool_t retval;
31514b11b2bSmrg
31614b11b2bSmrg    boxes64f = pixman_region64f_rectangles (src, &n_boxes);
31714b11b2bSmrg
31814b11b2bSmrg    if (n_boxes > N_TMP_BOXES)
31914b11b2bSmrg	boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t));
32014b11b2bSmrg    else
32114b11b2bSmrg	boxes32 = tmp_boxes;
32214b11b2bSmrg
32314b11b2bSmrg    if (!boxes32)
32414b11b2bSmrg	return FALSE;
32514b11b2bSmrg
32614b11b2bSmrg    for (i = 0; i < n_boxes; ++i)
32714b11b2bSmrg    {
32814b11b2bSmrg	boxes32[i].x1 = boxes64f[i].x1;
32914b11b2bSmrg	boxes32[i].y1 = boxes64f[i].y1;
33014b11b2bSmrg	boxes32[i].x2 = boxes64f[i].x2;
33114b11b2bSmrg	boxes32[i].y2 = boxes64f[i].y2;
33214b11b2bSmrg    }
33314b11b2bSmrg
33414b11b2bSmrg    pixman_region32_fini (dst);
33514b11b2bSmrg    retval = pixman_region32_init_rects (dst, boxes32, n_boxes);
33614b11b2bSmrg
33714b11b2bSmrg    if (boxes32 != tmp_boxes)
33814b11b2bSmrg	free (boxes32);
33914b11b2bSmrg
34014b11b2bSmrg    return retval;
34114b11b2bSmrg}
34214b11b2bSmrg
3439ad247e8Sjmcneill/* This function is exported for the sake of the test suite and not part
3449ad247e8Sjmcneill * of the ABI.
3459ad247e8Sjmcneill */
3469ad247e8SjmcneillPIXMAN_EXPORT pixman_implementation_t *
3479ad247e8Sjmcneill_pixman_internal_only_get_implementation (void)
3489ad247e8Sjmcneill{
3499ad247e8Sjmcneill    return get_implementation ();
3509ad247e8Sjmcneill}
3519ad247e8Sjmcneill
352952204abSmrgvoid
353952204abSmrg_pixman_log_error (const char *function, const char *message)
354952204abSmrg{
355952204abSmrg    static int n_messages = 0;
356952204abSmrg
357952204abSmrg    if (n_messages < 10)
358952204abSmrg    {
359952204abSmrg	fprintf (stderr,
360952204abSmrg		 "*** BUG ***\n"
361952204abSmrg		 "In %s: %s\n"
362952204abSmrg		 "Set a breakpoint on '_pixman_log_error' to debug\n\n",
363952204abSmrg                 function, message);
364952204abSmrg
365952204abSmrg	n_messages++;
366952204abSmrg    }
367952204abSmrg}
368