pixman-utils.c revision 953d7d37
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 31#include "pixman-private.h" 32 33pixman_bool_t 34pixman_multiply_overflows_int (unsigned int a, 35 unsigned int b) 36{ 37 return a >= INT32_MAX / b; 38} 39 40pixman_bool_t 41pixman_addition_overflows_int (unsigned int a, 42 unsigned int b) 43{ 44 return a > INT32_MAX - b; 45} 46 47void * 48pixman_malloc_ab (unsigned int a, 49 unsigned int b) 50{ 51 if (a >= INT32_MAX / b) 52 return NULL; 53 54 return malloc (a * b); 55} 56 57void * 58pixman_malloc_abc (unsigned int a, 59 unsigned int b, 60 unsigned int c) 61{ 62 if (a >= INT32_MAX / b) 63 return NULL; 64 else if (a * b >= INT32_MAX / c) 65 return NULL; 66 else 67 return malloc (a * b * c); 68} 69 70/* 71 * Helper routine to expand a color component from 0 < n <= 8 bits to 16 72 * bits by replication. 73 */ 74static inline uint64_t 75expand16 (const uint8_t val, int nbits) 76{ 77 /* Start out with the high bit of val in the high bit of result. */ 78 uint16_t result = (uint16_t)val << (16 - nbits); 79 80 if (nbits == 0) 81 return 0; 82 83 /* Copy the bits in result, doubling the number of bits each time, until 84 * we fill all 16 bits. 85 */ 86 while (nbits < 16) 87 { 88 result |= result >> nbits; 89 nbits *= 2; 90 } 91 92 return result; 93} 94 95/* 96 * This function expands images from ARGB8 format to ARGB16. To preserve 97 * precision, it needs to know the original source format. For example, if the 98 * source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then 99 * the expanded value is 12345123. To correctly expand this to 16 bits, it 100 * should be 1234512345123451 and not 1234512312345123. 101 */ 102void 103pixman_expand (uint64_t * dst, 104 const uint32_t * src, 105 pixman_format_code_t format, 106 int width) 107{ 108 /* 109 * Determine the sizes of each component and the masks and shifts 110 * required to extract them from the source pixel. 111 */ 112 const int a_size = PIXMAN_FORMAT_A (format), 113 r_size = PIXMAN_FORMAT_R (format), 114 g_size = PIXMAN_FORMAT_G (format), 115 b_size = PIXMAN_FORMAT_B (format); 116 const int a_shift = 32 - a_size, 117 r_shift = 24 - r_size, 118 g_shift = 16 - g_size, 119 b_shift = 8 - b_size; 120 const uint8_t a_mask = ~(~0 << a_size), 121 r_mask = ~(~0 << r_size), 122 g_mask = ~(~0 << g_size), 123 b_mask = ~(~0 << b_size); 124 int i; 125 126 /* Start at the end so that we can do the expansion in place 127 * when src == dst 128 */ 129 for (i = width - 1; i >= 0; i--) 130 { 131 const uint32_t pixel = src[i]; 132 const uint8_t a = (pixel >> a_shift) & a_mask, 133 r = (pixel >> r_shift) & r_mask, 134 g = (pixel >> g_shift) & g_mask, 135 b = (pixel >> b_shift) & b_mask; 136 const uint64_t a16 = a_size ? expand16 (a, a_size) : 0xffff, 137 r16 = expand16 (r, r_size), 138 g16 = expand16 (g, g_size), 139 b16 = expand16 (b, b_size); 140 141 dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16; 142 } 143} 144 145/* 146 * Contracting is easier than expanding. We just need to truncate the 147 * components. 148 */ 149void 150pixman_contract (uint32_t * dst, 151 const uint64_t *src, 152 int width) 153{ 154 int i; 155 156 /* Start at the beginning so that we can do the contraction in 157 * place when src == dst 158 */ 159 for (i = 0; i < width; i++) 160 { 161 const uint8_t a = src[i] >> 56, 162 r = src[i] >> 40, 163 g = src[i] >> 24, 164 b = src[i] >> 8; 165 166 dst[i] = a << 24 | r << 16 | g << 8 | b; 167 } 168} 169 170uint32_t * 171_pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask) 172{ 173 return iter->buffer; 174} 175 176#define N_TMP_BOXES (16) 177 178pixman_bool_t 179pixman_region16_copy_from_region32 (pixman_region16_t *dst, 180 pixman_region32_t *src) 181{ 182 int n_boxes, i; 183 pixman_box32_t *boxes32; 184 pixman_box16_t *boxes16; 185 pixman_bool_t retval; 186 187 boxes32 = pixman_region32_rectangles (src, &n_boxes); 188 189 boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t)); 190 191 if (!boxes16) 192 return FALSE; 193 194 for (i = 0; i < n_boxes; ++i) 195 { 196 boxes16[i].x1 = boxes32[i].x1; 197 boxes16[i].y1 = boxes32[i].y1; 198 boxes16[i].x2 = boxes32[i].x2; 199 boxes16[i].y2 = boxes32[i].y2; 200 } 201 202 pixman_region_fini (dst); 203 retval = pixman_region_init_rects (dst, boxes16, n_boxes); 204 free (boxes16); 205 return retval; 206} 207 208pixman_bool_t 209pixman_region32_copy_from_region16 (pixman_region32_t *dst, 210 pixman_region16_t *src) 211{ 212 int n_boxes, i; 213 pixman_box16_t *boxes16; 214 pixman_box32_t *boxes32; 215 pixman_box32_t tmp_boxes[N_TMP_BOXES]; 216 pixman_bool_t retval; 217 218 boxes16 = pixman_region_rectangles (src, &n_boxes); 219 220 if (n_boxes > N_TMP_BOXES) 221 boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t)); 222 else 223 boxes32 = tmp_boxes; 224 225 if (!boxes32) 226 return FALSE; 227 228 for (i = 0; i < n_boxes; ++i) 229 { 230 boxes32[i].x1 = boxes16[i].x1; 231 boxes32[i].y1 = boxes16[i].y1; 232 boxes32[i].x2 = boxes16[i].x2; 233 boxes32[i].y2 = boxes16[i].y2; 234 } 235 236 pixman_region32_fini (dst); 237 retval = pixman_region32_init_rects (dst, boxes32, n_boxes); 238 239 if (boxes32 != tmp_boxes) 240 free (boxes32); 241 242 return retval; 243} 244 245#ifdef DEBUG 246 247void 248_pixman_log_error (const char *function, const char *message) 249{ 250 static int n_messages = 0; 251 252 if (n_messages < 10) 253 { 254 fprintf (stderr, 255 "*** BUG ***\n" 256 "In %s: %s\n" 257 "Set a breakpoint on '_pixman_log_error' to debug\n\n", 258 function, message); 259 260 n_messages++; 261 } 262} 263 264#endif 265