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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial