tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pixman-general.c (8377B)


      1 /*
      2 * Copyright © 2009 Red Hat, Inc.
      3 * Copyright © 2000 SuSE, Inc.
      4 * Copyright © 2007 Red Hat, Inc.
      5 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
      6 *             2005 Lars Knoll & Zack Rusin, Trolltech
      7 *             2008 Aaron Plattner, NVIDIA Corporation
      8 *
      9 * Permission to use, copy, modify, distribute, and sell this software and its
     10 * documentation for any purpose is hereby granted without fee, provided that
     11 * the above copyright notice appear in all copies and that both that
     12 * copyright notice and this permission notice appear in supporting
     13 * documentation, and that the name of Red Hat not be used in advertising or
     14 * publicity pertaining to distribution of the software without specific,
     15 * written prior permission.  Red Hat makes no representations about the
     16 * suitability of this software for any purpose.  It is provided "as is"
     17 * without express or implied warranty.
     18 *
     19 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
     20 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
     21 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
     22 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
     24 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     25 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     26 * SOFTWARE.
     27 */
     28 #ifdef HAVE_CONFIG_H
     29 #include <pixman-config.h>
     30 #endif
     31 #include <stdlib.h>
     32 #include <string.h>
     33 #include <math.h>
     34 #include <limits.h>
     35 #include <stdio.h>
     36 #include <stdlib.h>
     37 #include <string.h>
     38 #include "pixman-private.h"
     39 
     40 static void
     41 general_iter_init (pixman_iter_t *iter, const pixman_iter_info_t *info)
     42 {
     43    pixman_image_t *image = iter->image;
     44 
     45    switch (image->type)
     46    {
     47    case BITS:
     48        if ((iter->iter_flags & ITER_SRC) == ITER_SRC)
     49            _pixman_bits_image_src_iter_init (image, iter);
     50        else
     51            _pixman_bits_image_dest_iter_init (image, iter);
     52        break;
     53 
     54    case LINEAR:
     55        _pixman_linear_gradient_iter_init (image, iter);
     56        break;
     57 
     58    case RADIAL:
     59 _pixman_radial_gradient_iter_init (image, iter);
     60        break;
     61 
     62    case CONICAL:
     63 _pixman_conical_gradient_iter_init (image, iter);
     64        break;
     65 
     66    case SOLID:
     67        _pixman_log_error (FUNC, "Solid image not handled by noop");
     68        break;
     69 
     70    default:
     71 _pixman_log_error (FUNC, "Pixman bug: unknown image type\n");
     72        break;
     73    }
     74 }
     75 
     76 static const pixman_iter_info_t general_iters[] =
     77 {
     78    { PIXMAN_any, 0, 0, general_iter_init, NULL, NULL },
     79    { PIXMAN_null },
     80 };
     81 
     82 typedef struct op_info_t op_info_t;
     83 struct op_info_t
     84 {
     85    uint8_t src, dst;
     86 };
     87 
     88 #define ITER_IGNORE_BOTH						\
     89    (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_LOCALIZED_ALPHA)
     90 
     91 static const op_info_t op_flags[PIXMAN_N_OPERATORS] =
     92 {
     93    /* Src                   Dst                   */
     94    { ITER_IGNORE_BOTH,      ITER_IGNORE_BOTH      }, /* CLEAR */
     95    { ITER_LOCALIZED_ALPHA,  ITER_IGNORE_BOTH      }, /* SRC */
     96    { ITER_IGNORE_BOTH,      ITER_LOCALIZED_ALPHA  }, /* DST */
     97    { 0,                     ITER_LOCALIZED_ALPHA  }, /* OVER */
     98    { ITER_LOCALIZED_ALPHA,  0                     }, /* OVER_REVERSE */
     99    { ITER_LOCALIZED_ALPHA,  ITER_IGNORE_RGB       }, /* IN */
    100    { ITER_IGNORE_RGB,       ITER_LOCALIZED_ALPHA  }, /* IN_REVERSE */
    101    { ITER_LOCALIZED_ALPHA,  ITER_IGNORE_RGB       }, /* OUT */
    102    { ITER_IGNORE_RGB,       ITER_LOCALIZED_ALPHA  }, /* OUT_REVERSE */
    103    { 0,                     0                     }, /* ATOP */
    104    { 0,                     0                     }, /* ATOP_REVERSE */
    105    { 0,                     0                     }, /* XOR */
    106    { ITER_LOCALIZED_ALPHA,  ITER_LOCALIZED_ALPHA  }, /* ADD */
    107    { 0,                     0                     }, /* SATURATE */
    108 };
    109 
    110 #define SCANLINE_BUFFER_LENGTH 8192
    111 
    112 static pixman_bool_t
    113 operator_needs_division (pixman_op_t op)
    114 {
    115    static const uint8_t needs_division[] =
    116    {
    117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, /* SATURATE */
    118 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, /* DISJOINT */
    119 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, /* CONJOINT */
    120 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, /* blend ops */
    121    };
    122 
    123    return needs_division[op];
    124 }
    125 
    126 static void
    127 general_composite_rect  (pixman_implementation_t *imp,
    128                         pixman_composite_info_t *info)
    129 {
    130    PIXMAN_COMPOSITE_ARGS (info);
    131    uint8_t stack_scanline_buffer[3 * SCANLINE_BUFFER_LENGTH];
    132    uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
    133    uint8_t *src_buffer, *mask_buffer, *dest_buffer;
    134    pixman_iter_t src_iter, mask_iter, dest_iter;
    135    pixman_combine_32_func_t compose;
    136    pixman_bool_t component_alpha;
    137    iter_flags_t width_flag, src_iter_flags;
    138    int Bpp;
    139    int i;
    140 
    141    if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT)		     &&
    142 (!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT)  &&
    143 (dest_image->common.flags & FAST_PATH_NARROW_FORMAT)		     &&
    144 !(operator_needs_division (op))                                      &&
    145 (dest_image->bits.dither == PIXMAN_DITHER_NONE))
    146    {
    147 width_flag = ITER_NARROW;
    148 Bpp = 4;
    149    }
    150    else
    151    {
    152 width_flag = ITER_WIDE;
    153 Bpp = 16;
    154    }
    155 
    156 #define ALIGN(addr)							\
    157    ((uint8_t *)((((uintptr_t)(addr)) + 15) & (~15)))
    158 
    159    if (width <= 0 || _pixman_multiply_overflows_int (width, Bpp * 3))
    160 return;
    161 
    162    if (width * Bpp * 3 > sizeof (stack_scanline_buffer) - 15 * 3)
    163    {
    164 scanline_buffer = pixman_malloc_ab_plus_c (width, Bpp * 3, 15 * 3);
    165 
    166 if (!scanline_buffer)
    167     return;
    168 
    169 memset (scanline_buffer, 0, width * Bpp * 3 + 15 * 3);
    170    }
    171    else
    172    {
    173 memset (stack_scanline_buffer, 0, sizeof (stack_scanline_buffer));
    174    }
    175 
    176    src_buffer = ALIGN (scanline_buffer);
    177    mask_buffer = ALIGN (src_buffer + width * Bpp);
    178    dest_buffer = ALIGN (mask_buffer + width * Bpp);
    179 
    180    if (width_flag == ITER_WIDE)
    181    {
    182 /* To make sure there aren't any NANs in the buffers */
    183 memset (src_buffer, 0, width * Bpp);
    184 memset (mask_buffer, 0, width * Bpp);
    185 memset (dest_buffer, 0, width * Bpp);
    186    }
    187    
    188    /* src iter */
    189    src_iter_flags = width_flag | op_flags[op].src | ITER_SRC;
    190 
    191    _pixman_implementation_iter_init (imp->toplevel, &src_iter, src_image,
    192                                      src_x, src_y, width, height,
    193                                      src_buffer, src_iter_flags,
    194                                      info->src_flags);
    195 
    196    /* mask iter */
    197    if ((src_iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
    198 (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
    199    {
    200 /* If it doesn't matter what the source is, then it doesn't matter
    201  * what the mask is
    202  */
    203 mask_image = NULL;
    204    }
    205 
    206    component_alpha = mask_image && mask_image->common.component_alpha;
    207 
    208    _pixman_implementation_iter_init (
    209 imp->toplevel, &mask_iter,
    210 mask_image, mask_x, mask_y, width, height, mask_buffer,
    211 ITER_SRC | width_flag | (component_alpha? 0 : ITER_IGNORE_RGB),
    212 info->mask_flags);
    213 
    214    /* dest iter */
    215    _pixman_implementation_iter_init (
    216 imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height,
    217 dest_buffer, ITER_DEST | width_flag | op_flags[op].dst, info->dest_flags);
    218 
    219    compose = _pixman_implementation_lookup_combiner (
    220 imp->toplevel, op, component_alpha, width_flag != ITER_WIDE);
    221 
    222    for (i = 0; i < height; ++i)
    223    {
    224 uint32_t *s, *m, *d;
    225 
    226 m = mask_iter.get_scanline (&mask_iter, NULL);
    227 s = src_iter.get_scanline (&src_iter, m);
    228 d = dest_iter.get_scanline (&dest_iter, NULL);
    229 
    230 compose (imp->toplevel, op, d, s, m, width);
    231 
    232 dest_iter.write_back (&dest_iter);
    233    }
    234 
    235    if (src_iter.fini)
    236 src_iter.fini (&src_iter);
    237    if (mask_iter.fini)
    238 mask_iter.fini (&mask_iter);
    239    if (dest_iter.fini)
    240 dest_iter.fini (&dest_iter);
    241    
    242    if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
    243 free (scanline_buffer);
    244 }
    245 
    246 static const pixman_fast_path_t general_fast_path[] =
    247 {
    248    { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any,	0, PIXMAN_any, 0, general_composite_rect },
    249    { PIXMAN_OP_NONE }
    250 };
    251 
    252 pixman_implementation_t *
    253 _pixman_implementation_create_general (void)
    254 {
    255    pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
    256 
    257    _pixman_setup_combiner_functions_32 (imp);
    258    _pixman_setup_combiner_functions_float (imp);
    259 
    260    imp->iter_info = general_iters;
    261 
    262    return imp;
    263 }