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