gfx/cairo/libpixman/src/pixman-utils.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/libpixman/src/pixman-utils.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,315 @@
     1.4 +/*
     1.5 + * Copyright © 2000 SuSE, Inc.
     1.6 + * Copyright © 1999 Keith Packard
     1.7 + *
     1.8 + * Permission to use, copy, modify, distribute, and sell this software and its
     1.9 + * documentation for any purpose is hereby granted without fee, provided that
    1.10 + * the above copyright notice appear in all copies and that both that
    1.11 + * copyright notice and this permission notice appear in supporting
    1.12 + * documentation, and that the name of SuSE not be used in advertising or
    1.13 + * publicity pertaining to distribution of the software without specific,
    1.14 + * written prior permission.  SuSE makes no representations about the
    1.15 + * suitability of this software for any purpose.  It is provided "as is"
    1.16 + * without express or implied warranty.
    1.17 + *
    1.18 + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
    1.19 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
    1.20 + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    1.21 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
    1.22 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
    1.23 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    1.24 + *
    1.25 + * Author:  Keith Packard, SuSE, Inc.
    1.26 + */
    1.27 +
    1.28 +#ifdef HAVE_CONFIG_H
    1.29 +#include <config.h>
    1.30 +#endif
    1.31 +#include <stdio.h>
    1.32 +#include <stdlib.h>
    1.33 +#include <limits.h>
    1.34 +
    1.35 +#include "pixman-private.h"
    1.36 +
    1.37 +pixman_bool_t
    1.38 +_pixman_multiply_overflows_size (size_t a, size_t b)
    1.39 +{
    1.40 +    return a >= SIZE_MAX / b;
    1.41 +}
    1.42 +
    1.43 +pixman_bool_t
    1.44 +_pixman_multiply_overflows_int (unsigned int a, unsigned int b)
    1.45 +{
    1.46 +    return a >= INT32_MAX / b;
    1.47 +}
    1.48 +
    1.49 +pixman_bool_t
    1.50 +_pixman_addition_overflows_int (unsigned int a, unsigned int b)
    1.51 +{
    1.52 +    return a > INT32_MAX - b;
    1.53 +}
    1.54 +
    1.55 +void *
    1.56 +pixman_malloc_ab (unsigned int a,
    1.57 +                  unsigned int b)
    1.58 +{
    1.59 +    if (a >= INT32_MAX / b)
    1.60 +	return NULL;
    1.61 +
    1.62 +    return malloc (a * b);
    1.63 +}
    1.64 +
    1.65 +void *
    1.66 +pixman_malloc_abc (unsigned int a,
    1.67 +                   unsigned int b,
    1.68 +                   unsigned int c)
    1.69 +{
    1.70 +    if (a >= INT32_MAX / b)
    1.71 +	return NULL;
    1.72 +    else if (a * b >= INT32_MAX / c)
    1.73 +	return NULL;
    1.74 +    else
    1.75 +	return malloc (a * b * c);
    1.76 +}
    1.77 +
    1.78 +static force_inline uint16_t
    1.79 +float_to_unorm (float f, int n_bits)
    1.80 +{
    1.81 +    uint32_t u;
    1.82 +
    1.83 +    if (f > 1.0)
    1.84 +	f = 1.0;
    1.85 +    if (f < 0.0)
    1.86 +	f = 0.0;
    1.87 +
    1.88 +    u = f * (1 << n_bits);
    1.89 +    u -= (u >> n_bits);
    1.90 +
    1.91 +    return u;
    1.92 +}
    1.93 +
    1.94 +static force_inline float
    1.95 +unorm_to_float (uint16_t u, int n_bits)
    1.96 +{
    1.97 +    uint32_t m = ((1 << n_bits) - 1);
    1.98 +
    1.99 +    return (u & m) * (1.f / (float)m);
   1.100 +}
   1.101 +
   1.102 +/*
   1.103 + * This function expands images from a8r8g8b8 to argb_t.  To preserve
   1.104 + * precision, it needs to know from which source format the a8r8g8b8 pixels
   1.105 + * originally came.
   1.106 + *
   1.107 + * For example, if the source was PIXMAN_x1r5g5b5 and the red component
   1.108 + * contained bits 12345, then the 8-bit value is 12345123.  To correctly
   1.109 + * expand this to floating point, it should be 12345 / 31.0 and not
   1.110 + * 12345123 / 255.0.
   1.111 + */
   1.112 +void
   1.113 +pixman_expand_to_float (argb_t               *dst,
   1.114 +			const uint32_t       *src,
   1.115 +			pixman_format_code_t  format,
   1.116 +			int                   width)
   1.117 +{
   1.118 +    static const float multipliers[16] = {
   1.119 +	0.0f,
   1.120 +	1.0f / ((1 <<  1) - 1),
   1.121 +	1.0f / ((1 <<  2) - 1),
   1.122 +	1.0f / ((1 <<  3) - 1),
   1.123 +	1.0f / ((1 <<  4) - 1),
   1.124 +	1.0f / ((1 <<  5) - 1),
   1.125 +	1.0f / ((1 <<  6) - 1),
   1.126 +	1.0f / ((1 <<  7) - 1),
   1.127 +	1.0f / ((1 <<  8) - 1),
   1.128 +	1.0f / ((1 <<  9) - 1),
   1.129 +	1.0f / ((1 << 10) - 1),
   1.130 +	1.0f / ((1 << 11) - 1),
   1.131 +	1.0f / ((1 << 12) - 1),
   1.132 +	1.0f / ((1 << 13) - 1),
   1.133 +	1.0f / ((1 << 14) - 1),
   1.134 +	1.0f / ((1 << 15) - 1),
   1.135 +    };
   1.136 +    int a_size, r_size, g_size, b_size;
   1.137 +    int a_shift, r_shift, g_shift, b_shift;
   1.138 +    float a_mul, r_mul, g_mul, b_mul;
   1.139 +    uint32_t a_mask, r_mask, g_mask, b_mask;
   1.140 +    int i;
   1.141 +
   1.142 +    if (!PIXMAN_FORMAT_VIS (format))
   1.143 +	format = PIXMAN_a8r8g8b8;
   1.144 +
   1.145 +    /*
   1.146 +     * Determine the sizes of each component and the masks and shifts
   1.147 +     * required to extract them from the source pixel.
   1.148 +     */
   1.149 +    a_size = PIXMAN_FORMAT_A (format);
   1.150 +    r_size = PIXMAN_FORMAT_R (format);
   1.151 +    g_size = PIXMAN_FORMAT_G (format);
   1.152 +    b_size = PIXMAN_FORMAT_B (format);
   1.153 +
   1.154 +    a_shift = 32 - a_size;
   1.155 +    r_shift = 24 - r_size;
   1.156 +    g_shift = 16 - g_size;
   1.157 +    b_shift =  8 - b_size;
   1.158 +
   1.159 +    a_mask = ((1 << a_size) - 1);
   1.160 +    r_mask = ((1 << r_size) - 1);
   1.161 +    g_mask = ((1 << g_size) - 1);
   1.162 +    b_mask = ((1 << b_size) - 1);
   1.163 +
   1.164 +    a_mul = multipliers[a_size];
   1.165 +    r_mul = multipliers[r_size];
   1.166 +    g_mul = multipliers[g_size];
   1.167 +    b_mul = multipliers[b_size];
   1.168 +
   1.169 +    /* Start at the end so that we can do the expansion in place
   1.170 +     * when src == dst
   1.171 +     */
   1.172 +    for (i = width - 1; i >= 0; i--)
   1.173 +    {
   1.174 +	const uint32_t pixel = src[i];
   1.175 +
   1.176 +	dst[i].a = a_mask? ((pixel >> a_shift) & a_mask) * a_mul : 1.0f;
   1.177 +	dst[i].r = ((pixel >> r_shift) & r_mask) * r_mul;
   1.178 +	dst[i].g = ((pixel >> g_shift) & g_mask) * g_mul;
   1.179 +	dst[i].b = ((pixel >> b_shift) & b_mask) * b_mul;
   1.180 +    }
   1.181 +}
   1.182 +
   1.183 +uint16_t
   1.184 +pixman_float_to_unorm (float f, int n_bits)
   1.185 +{
   1.186 +    return float_to_unorm (f, n_bits);
   1.187 +}
   1.188 +
   1.189 +float
   1.190 +pixman_unorm_to_float (uint16_t u, int n_bits)
   1.191 +{
   1.192 +    return unorm_to_float (u, n_bits);
   1.193 +}
   1.194 +
   1.195 +void
   1.196 +pixman_contract_from_float (uint32_t     *dst,
   1.197 +			    const argb_t *src,
   1.198 +			    int           width)
   1.199 +{
   1.200 +    int i;
   1.201 +
   1.202 +    for (i = 0; i < width; ++i)
   1.203 +    {
   1.204 +	uint8_t a, r, g, b;
   1.205 +
   1.206 +	a = float_to_unorm (src[i].a, 8);
   1.207 +	r = float_to_unorm (src[i].r, 8);
   1.208 +	g = float_to_unorm (src[i].g, 8);
   1.209 +	b = float_to_unorm (src[i].b, 8);
   1.210 +
   1.211 +	dst[i] = (a << 24) | (r << 16) | (g << 8) | (b << 0);
   1.212 +    }
   1.213 +}
   1.214 +
   1.215 +uint32_t *
   1.216 +_pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask)
   1.217 +{
   1.218 +    return iter->buffer;
   1.219 +}
   1.220 +
   1.221 +#define N_TMP_BOXES (16)
   1.222 +
   1.223 +pixman_bool_t
   1.224 +pixman_region16_copy_from_region32 (pixman_region16_t *dst,
   1.225 +                                    pixman_region32_t *src)
   1.226 +{
   1.227 +    int n_boxes, i;
   1.228 +    pixman_box32_t *boxes32;
   1.229 +    pixman_box16_t *boxes16;
   1.230 +    pixman_bool_t retval;
   1.231 +
   1.232 +    boxes32 = pixman_region32_rectangles (src, &n_boxes);
   1.233 +
   1.234 +    boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t));
   1.235 +
   1.236 +    if (!boxes16)
   1.237 +	return FALSE;
   1.238 +
   1.239 +    for (i = 0; i < n_boxes; ++i)
   1.240 +    {
   1.241 +	boxes16[i].x1 = boxes32[i].x1;
   1.242 +	boxes16[i].y1 = boxes32[i].y1;
   1.243 +	boxes16[i].x2 = boxes32[i].x2;
   1.244 +	boxes16[i].y2 = boxes32[i].y2;
   1.245 +    }
   1.246 +
   1.247 +    pixman_region_fini (dst);
   1.248 +    retval = pixman_region_init_rects (dst, boxes16, n_boxes);
   1.249 +    free (boxes16);
   1.250 +    return retval;
   1.251 +}
   1.252 +
   1.253 +pixman_bool_t
   1.254 +pixman_region32_copy_from_region16 (pixman_region32_t *dst,
   1.255 +                                    pixman_region16_t *src)
   1.256 +{
   1.257 +    int n_boxes, i;
   1.258 +    pixman_box16_t *boxes16;
   1.259 +    pixman_box32_t *boxes32;
   1.260 +    pixman_box32_t tmp_boxes[N_TMP_BOXES];
   1.261 +    pixman_bool_t retval;
   1.262 +
   1.263 +    boxes16 = pixman_region_rectangles (src, &n_boxes);
   1.264 +
   1.265 +    if (n_boxes > N_TMP_BOXES)
   1.266 +	boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t));
   1.267 +    else
   1.268 +	boxes32 = tmp_boxes;
   1.269 +
   1.270 +    if (!boxes32)
   1.271 +	return FALSE;
   1.272 +
   1.273 +    for (i = 0; i < n_boxes; ++i)
   1.274 +    {
   1.275 +	boxes32[i].x1 = boxes16[i].x1;
   1.276 +	boxes32[i].y1 = boxes16[i].y1;
   1.277 +	boxes32[i].x2 = boxes16[i].x2;
   1.278 +	boxes32[i].y2 = boxes16[i].y2;
   1.279 +    }
   1.280 +
   1.281 +    pixman_region32_fini (dst);
   1.282 +    retval = pixman_region32_init_rects (dst, boxes32, n_boxes);
   1.283 +
   1.284 +    if (boxes32 != tmp_boxes)
   1.285 +	free (boxes32);
   1.286 +
   1.287 +    return retval;
   1.288 +}
   1.289 +
   1.290 +/* This function is exported for the sake of the test suite and not part
   1.291 + * of the ABI.
   1.292 + */
   1.293 +PIXMAN_EXPORT pixman_implementation_t *
   1.294 +_pixman_internal_only_get_implementation (void)
   1.295 +{
   1.296 +    return get_implementation ();
   1.297 +}
   1.298 +
   1.299 +#ifdef DEBUG
   1.300 +
   1.301 +void
   1.302 +_pixman_log_error (const char *function, const char *message)
   1.303 +{
   1.304 +    static int n_messages = 0;
   1.305 +
   1.306 +    if (n_messages < 10)
   1.307 +    {
   1.308 +	fprintf (stderr,
   1.309 +		 "*** BUG ***\n"
   1.310 +		 "In %s: %s\n"
   1.311 +		 "Set a breakpoint on '_pixman_log_error' to debug\n\n",
   1.312 +                 function, message);
   1.313 +
   1.314 +	n_messages++;
   1.315 +    }
   1.316 +}
   1.317 +
   1.318 +#endif

mercurial