tor-browser

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

pixman.c (37021B)


      1 /* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
      2 /*
      3 * Copyright © 2000 SuSE, Inc.
      4 * Copyright © 2007 Red Hat, Inc.
      5 *
      6 * Permission to use, copy, modify, distribute, and sell this software and its
      7 * documentation for any purpose is hereby granted without fee, provided that
      8 * the above copyright notice appear in all copies and that both that
      9 * copyright notice and this permission notice appear in supporting
     10 * documentation, and that the name of SuSE not be used in advertising or
     11 * publicity pertaining to distribution of the software without specific,
     12 * written prior permission.  SuSE makes no representations about the
     13 * suitability of this software for any purpose.  It is provided "as is"
     14 * without express or implied warranty.
     15 *
     16 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
     17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
     18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     22 *
     23 * Author:  Keith Packard, SuSE, Inc.
     24 */
     25 
     26 #ifdef HAVE_CONFIG_H
     27 #include <pixman-config.h>
     28 #endif
     29 #include "pixman-private.h"
     30 
     31 #include <stdlib.h>
     32 
     33 pixman_implementation_t *global_implementation;
     34 
     35 #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
     36 static void __attribute__((constructor))
     37 pixman_constructor (void)
     38 {
     39    global_implementation = _pixman_choose_implementation ();
     40 }
     41 #endif
     42 
     43 #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_DESTRUCTOR
     44 static void __attribute__((destructor))
     45 pixman_destructor (void)
     46 {
     47    pixman_implementation_t *imp = global_implementation;
     48 
     49    while (imp)
     50    {
     51        pixman_implementation_t *cur = imp;
     52        imp = imp->fallback;
     53        free (cur);
     54    }
     55 }
     56 #endif
     57 
     58 typedef struct operator_info_t operator_info_t;
     59 
     60 struct operator_info_t
     61 {
     62    uint8_t	opaque_info[4];
     63 };
     64 
     65 #define PACK(neither, src, dest, both)			\
     66    {{	    (uint8_t)PIXMAN_OP_ ## neither,		\
     67     (uint8_t)PIXMAN_OP_ ## src,			\
     68     (uint8_t)PIXMAN_OP_ ## dest,		\
     69     (uint8_t)PIXMAN_OP_ ## both		}}
     70 
     71 static const operator_info_t operator_table[] =
     72 {
     73    /*    Neither Opaque         Src Opaque             Dst Opaque             Both Opaque */
     74    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
     75    PACK (SRC,                   SRC,                   SRC,                   SRC),
     76    PACK (DST,                   DST,                   DST,                   DST),
     77    PACK (OVER,                  SRC,                   OVER,                  SRC),
     78    PACK (OVER_REVERSE,          OVER_REVERSE,          DST,                   DST),
     79    PACK (IN,                    IN,                    SRC,                   SRC),
     80    PACK (IN_REVERSE,            DST,                   IN_REVERSE,            DST),
     81    PACK (OUT,                   OUT,                   CLEAR,                 CLEAR),
     82    PACK (OUT_REVERSE,           CLEAR,                 OUT_REVERSE,           CLEAR),
     83    PACK (ATOP,                  IN,                    OVER,                  SRC),
     84    PACK (ATOP_REVERSE,          OVER_REVERSE,          IN_REVERSE,            DST),
     85    PACK (XOR,                   OUT,                   OUT_REVERSE,           CLEAR),
     86    PACK (ADD,                   ADD,                   ADD,                   ADD),
     87    PACK (SATURATE,              OVER_REVERSE,          DST,                   DST),
     88 
     89    {{ 0 /* 0x0e */ }},
     90    {{ 0 /* 0x0f */ }},
     91 
     92    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
     93    PACK (SRC,                   SRC,                   SRC,                   SRC),
     94    PACK (DST,                   DST,                   DST,                   DST),
     95    PACK (DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER),
     96    PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE),
     97    PACK (DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN),
     98    PACK (DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE),
     99    PACK (DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT),
    100    PACK (DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE),
    101    PACK (DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP),
    102    PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE),
    103    PACK (DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR),
    104 
    105    {{ 0 /* 0x1c */ }},
    106    {{ 0 /* 0x1d */ }},
    107    {{ 0 /* 0x1e */ }},
    108    {{ 0 /* 0x1f */ }},
    109 
    110    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
    111    PACK (SRC,                   SRC,                   SRC,                   SRC),
    112    PACK (DST,                   DST,                   DST,                   DST),
    113    PACK (CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER),
    114    PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE),
    115    PACK (CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN),
    116    PACK (CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE),
    117    PACK (CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT),
    118    PACK (CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE),
    119    PACK (CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP),
    120    PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE),
    121    PACK (CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR),
    122 
    123    {{ 0 /* 0x2c */ }},
    124    {{ 0 /* 0x2d */ }},
    125    {{ 0 /* 0x2e */ }},
    126    {{ 0 /* 0x2f */ }},
    127 
    128    PACK (MULTIPLY,              MULTIPLY,              MULTIPLY,              MULTIPLY),
    129    PACK (SCREEN,                SCREEN,                SCREEN,                SCREEN),
    130    PACK (OVERLAY,               OVERLAY,               OVERLAY,               OVERLAY),
    131    PACK (DARKEN,                DARKEN,                DARKEN,                DARKEN),
    132    PACK (LIGHTEN,               LIGHTEN,               LIGHTEN,               LIGHTEN),
    133    PACK (COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE),
    134    PACK (COLOR_BURN,            COLOR_BURN,            COLOR_BURN,            COLOR_BURN),
    135    PACK (HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT),
    136    PACK (SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT),
    137    PACK (DIFFERENCE,            DIFFERENCE,            DIFFERENCE,            DIFFERENCE),
    138    PACK (EXCLUSION,             EXCLUSION,             EXCLUSION,             EXCLUSION),
    139    PACK (HSL_HUE,               HSL_HUE,               HSL_HUE,               HSL_HUE),
    140    PACK (HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION),
    141    PACK (HSL_COLOR,             HSL_COLOR,             HSL_COLOR,             HSL_COLOR),
    142    PACK (HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY),
    143 };
    144 
    145 /*
    146 * Optimize the current operator based on opacity of source or destination
    147 * The output operator should be mathematically equivalent to the source.
    148 */
    149 static pixman_op_t
    150 optimize_operator (pixman_op_t     op,
    151 	   uint32_t        src_flags,
    152 	   uint32_t        mask_flags,
    153 	   uint32_t        dst_flags)
    154 {
    155    pixman_bool_t is_source_opaque, is_dest_opaque;
    156 
    157 #define OPAQUE_SHIFT 13
    158    
    159    COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT));
    160    
    161    is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE);
    162    is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE);
    163 
    164    is_dest_opaque >>= OPAQUE_SHIFT - 1;
    165    is_source_opaque >>= OPAQUE_SHIFT;
    166 
    167    return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
    168 }
    169 
    170 /*
    171 * Computing composite region
    172 */
    173 static inline pixman_bool_t
    174 clip_general_image (pixman_region32_t * region,
    175                    pixman_region32_t * clip,
    176                    int                 dx,
    177                    int                 dy)
    178 {
    179    if (pixman_region32_n_rects (region) == 1 &&
    180        pixman_region32_n_rects (clip) == 1)
    181    {
    182 pixman_box32_t *  rbox = pixman_region32_rectangles (region, NULL);
    183 pixman_box32_t *  cbox = pixman_region32_rectangles (clip, NULL);
    184 int v;
    185 
    186 if (rbox->x1 < (v = cbox->x1 + dx))
    187     rbox->x1 = v;
    188 if (rbox->x2 > (v = cbox->x2 + dx))
    189     rbox->x2 = v;
    190 if (rbox->y1 < (v = cbox->y1 + dy))
    191     rbox->y1 = v;
    192 if (rbox->y2 > (v = cbox->y2 + dy))
    193     rbox->y2 = v;
    194 if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
    195 {
    196     pixman_region32_init (region);
    197     return FALSE;
    198 }
    199    }
    200    else if (pixman_region32_empty (clip))
    201    {
    202 return FALSE;
    203    }
    204    else
    205    {
    206 if (dx || dy)
    207     pixman_region32_translate (region, -dx, -dy);
    208 
    209 if (!pixman_region32_intersect (region, region, clip))
    210     return FALSE;
    211 
    212 if (dx || dy)
    213     pixman_region32_translate (region, dx, dy);
    214    }
    215 
    216    return pixman_region32_not_empty (region);
    217 }
    218 
    219 static inline pixman_bool_t
    220 clip_source_image (pixman_region32_t * region,
    221                   pixman_image_t *    image,
    222                   int                 dx,
    223                   int                 dy)
    224 {
    225    /* Source clips are ignored, unless they are explicitly turned on
    226     * and the clip in question was set by an X client. (Because if
    227     * the clip was not set by a client, then it is a hierarchy
    228     * clip and those should always be ignored for sources).
    229     */
    230    if (!image->common.clip_sources || !image->common.client_clip)
    231 return TRUE;
    232 
    233    return clip_general_image (region,
    234                               &image->common.clip_region,
    235                               dx, dy);
    236 }
    237 
    238 /*
    239 * returns FALSE if the final region is empty.  Indistinguishable from
    240 * an allocation failure, but rendering ignores those anyways.
    241 */
    242 pixman_bool_t
    243 _pixman_compute_composite_region32 (pixman_region32_t * region,
    244 			    pixman_image_t *    src_image,
    245 			    pixman_image_t *    mask_image,
    246 			    pixman_image_t *    dest_image,
    247 			    int32_t             src_x,
    248 			    int32_t             src_y,
    249 			    int32_t             mask_x,
    250 			    int32_t             mask_y,
    251 			    int32_t             dest_x,
    252 			    int32_t             dest_y,
    253 			    int32_t             width,
    254 			    int32_t             height)
    255 {
    256    region->extents.x1 = dest_x;
    257    region->extents.x2 = dest_x + width;
    258    region->extents.y1 = dest_y;
    259    region->extents.y2 = dest_y + height;
    260 
    261    region->extents.x1 = MAX (region->extents.x1, 0);
    262    region->extents.y1 = MAX (region->extents.y1, 0);
    263    region->extents.x2 = MIN (region->extents.x2, dest_image->bits.width);
    264    region->extents.y2 = MIN (region->extents.y2, dest_image->bits.height);
    265 
    266    region->data = 0;
    267 
    268    /* Check for empty operation */
    269    if (region->extents.x1 >= region->extents.x2 ||
    270        region->extents.y1 >= region->extents.y2)
    271    {
    272 region->extents.x1 = 0;
    273 region->extents.x2 = 0;
    274 region->extents.y1 = 0;
    275 region->extents.y2 = 0;
    276 return FALSE;
    277    }
    278 
    279    if (dest_image->common.have_clip_region)
    280    {
    281 if (!clip_general_image (region, &dest_image->common.clip_region, 0, 0))
    282     return FALSE;
    283    }
    284 
    285    if (dest_image->common.alpha_map)
    286    {
    287 if (!pixman_region32_intersect_rect (region, region,
    288 				     dest_image->common.alpha_origin_x,
    289 				     dest_image->common.alpha_origin_y,
    290 				     dest_image->common.alpha_map->width,
    291 				     dest_image->common.alpha_map->height))
    292 {
    293     return FALSE;
    294 }
    295 if (pixman_region32_empty (region))
    296     return FALSE;
    297 if (dest_image->common.alpha_map->common.have_clip_region)
    298 {
    299     if (!clip_general_image (region, &dest_image->common.alpha_map->common.clip_region,
    300 			     -dest_image->common.alpha_origin_x,
    301 			     -dest_image->common.alpha_origin_y))
    302     {
    303 	return FALSE;
    304     }
    305 }
    306    }
    307 
    308    /* clip against src */
    309    if (src_image->common.have_clip_region)
    310    {
    311 if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
    312     return FALSE;
    313    }
    314    if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
    315    {
    316 if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
    317                         dest_x - (src_x - src_image->common.alpha_origin_x),
    318                         dest_y - (src_y - src_image->common.alpha_origin_y)))
    319 {
    320     return FALSE;
    321 }
    322    }
    323    /* clip against mask */
    324    if (mask_image && mask_image->common.have_clip_region)
    325    {
    326 if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
    327     return FALSE;
    328 
    329 if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
    330 {
    331     if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
    332                             dest_x - (mask_x - mask_image->common.alpha_origin_x),
    333                             dest_y - (mask_y - mask_image->common.alpha_origin_y)))
    334     {
    335 	return FALSE;
    336     }
    337 }
    338    }
    339 
    340    return TRUE;
    341 }
    342 
    343 typedef struct box_48_16 box_48_16_t;
    344 
    345 struct box_48_16
    346 {
    347    pixman_fixed_48_16_t        x1;
    348    pixman_fixed_48_16_t        y1;
    349    pixman_fixed_48_16_t        x2;
    350    pixman_fixed_48_16_t        y2;
    351 };
    352 
    353 static pixman_bool_t
    354 compute_transformed_extents (pixman_transform_t   *transform,
    355 		     const pixman_box32_t *extents,
    356 		     box_48_16_t          *transformed)
    357 {
    358    pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
    359    pixman_fixed_t x1, y1, x2, y2;
    360    int i;
    361 
    362    x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2;
    363    y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2;
    364    x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2;
    365    y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2;
    366 
    367    if (!transform)
    368    {
    369 transformed->x1 = x1;
    370 transformed->y1 = y1;
    371 transformed->x2 = x2;
    372 transformed->y2 = y2;
    373 
    374 return TRUE;
    375    }
    376 
    377    tx1 = ty1 = INT64_MAX;
    378    tx2 = ty2 = INT64_MIN;
    379 
    380    for (i = 0; i < 4; ++i)
    381    {
    382 pixman_fixed_48_16_t tx, ty;
    383 pixman_vector_t v;
    384 
    385 v.vector[0] = (i & 0x01)? x1 : x2;
    386 v.vector[1] = (i & 0x02)? y1 : y2;
    387 v.vector[2] = pixman_fixed_1;
    388 
    389 if (!pixman_transform_point (transform, &v))
    390     return FALSE;
    391 
    392 tx = (pixman_fixed_48_16_t)v.vector[0];
    393 ty = (pixman_fixed_48_16_t)v.vector[1];
    394 
    395 if (tx < tx1)
    396     tx1 = tx;
    397 if (ty < ty1)
    398     ty1 = ty;
    399 if (tx > tx2)
    400     tx2 = tx;
    401 if (ty > ty2)
    402     ty2 = ty;
    403    }
    404 
    405    transformed->x1 = tx1;
    406    transformed->y1 = ty1;
    407    transformed->x2 = tx2;
    408    transformed->y2 = ty2;
    409 
    410    return TRUE;
    411 }
    412 
    413 #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
    414 #define ABS(f)      (((f) < 0)?  (-(f)) : (f))
    415 #define IS_16_16(f) (((f) >= pixman_min_fixed_48_16 && ((f) <= pixman_max_fixed_48_16)))
    416 
    417 static pixman_bool_t
    418 analyze_extent (pixman_image_t       *image,
    419 	const pixman_box32_t *extents,
    420 	uint32_t             *flags)
    421 {
    422    pixman_transform_t *transform;
    423    pixman_fixed_t x_off, y_off;
    424    pixman_fixed_t width, height;
    425    pixman_fixed_t *params;
    426    box_48_16_t transformed;
    427    pixman_box32_t exp_extents;
    428 
    429    if (!image)
    430 return TRUE;
    431 
    432    /* Some compositing functions walk one step
    433     * outside the destination rectangle, so we
    434     * check here that the expanded-by-one source
    435     * extents in destination space fits in 16 bits
    436     */
    437    if (!IS_16BIT (extents->x1 - 1)		||
    438 !IS_16BIT (extents->y1 - 1)		||
    439 !IS_16BIT (extents->x2 + 1)		||
    440 !IS_16BIT (extents->y2 + 1))
    441    {
    442 return FALSE;
    443    }
    444 
    445    transform = image->common.transform;
    446    if (image->common.type == BITS)
    447    {
    448 /* During repeat mode calculations we might convert the
    449  * width/height of an image to fixed 16.16, so we need
    450  * them to be smaller than 16 bits.
    451  */
    452 if (image->bits.width >= 0x7fff	|| image->bits.height >= 0x7fff)
    453     return FALSE;
    454 
    455 if ((image->common.flags & FAST_PATH_ID_TRANSFORM) == FAST_PATH_ID_TRANSFORM &&
    456     extents->x1 >= 0 &&
    457     extents->y1 >= 0 &&
    458     extents->x2 <= image->bits.width &&
    459     extents->y2 <= image->bits.height)
    460 {
    461     *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
    462     return TRUE;
    463 }
    464 
    465 switch (image->common.filter)
    466 {
    467 case PIXMAN_FILTER_CONVOLUTION:
    468     params = image->common.filter_params;
    469     x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
    470     y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
    471     width = params[0];
    472     height = params[1];
    473     break;
    474 
    475 case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
    476     params = image->common.filter_params;
    477     x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
    478     y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
    479     width = params[0];
    480     height = params[1];
    481     break;
    482     
    483 case PIXMAN_FILTER_GOOD:
    484 case PIXMAN_FILTER_BEST:
    485 case PIXMAN_FILTER_BILINEAR:
    486     x_off = - pixman_fixed_1 / 2;
    487     y_off = - pixman_fixed_1 / 2;
    488     width = pixman_fixed_1;
    489     height = pixman_fixed_1;
    490     break;
    491 
    492 case PIXMAN_FILTER_FAST:
    493 case PIXMAN_FILTER_NEAREST:
    494     x_off = - pixman_fixed_e;
    495     y_off = - pixman_fixed_e;
    496     width = 0;
    497     height = 0;
    498     break;
    499 
    500 default:
    501     return FALSE;
    502 }
    503    }
    504    else
    505    {
    506 x_off = 0;
    507 y_off = 0;
    508 width = 0;
    509 height = 0;
    510    }
    511 
    512    if (!compute_transformed_extents (transform, extents, &transformed))
    513 return FALSE;
    514 
    515    if (image->common.type == BITS)
    516    {
    517 if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_e) >= 0                &&
    518     pixman_fixed_to_int (transformed.y1 - pixman_fixed_e) >= 0                &&
    519     pixman_fixed_to_int (transformed.x2 - pixman_fixed_e) < image->bits.width &&
    520     pixman_fixed_to_int (transformed.y2 - pixman_fixed_e) < image->bits.height)
    521 {
    522     *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
    523 }
    524 
    525 if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_1 / 2) >= 0		  &&
    526     pixman_fixed_to_int (transformed.y1 - pixman_fixed_1 / 2) >= 0		  &&
    527     pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2) < image->bits.width &&
    528     pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2) < image->bits.height)
    529 {
    530     *flags |= FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR;
    531 }
    532    }
    533 
    534    /* Check we don't overflow when the destination extents are expanded by one.
    535     * This ensures that compositing functions can simply walk the source space
    536     * using 16.16 variables without worrying about overflow.
    537     */
    538    exp_extents = *extents;
    539    exp_extents.x1 -= 1;
    540    exp_extents.y1 -= 1;
    541    exp_extents.x2 += 1;
    542    exp_extents.y2 += 1;
    543 
    544    if (!compute_transformed_extents (transform, &exp_extents, &transformed))
    545 return FALSE;
    546    
    547    if (!IS_16_16 (transformed.x1 + x_off - 8 * pixman_fixed_e)	||
    548 !IS_16_16 (transformed.y1 + y_off - 8 * pixman_fixed_e)	||
    549 !IS_16_16 (transformed.x2 + x_off + 8 * pixman_fixed_e + width)	||
    550 !IS_16_16 (transformed.y2 + y_off + 8 * pixman_fixed_e + height))
    551    {
    552 return FALSE;
    553    }
    554 
    555    return TRUE;
    556 }
    557 
    558 /*
    559 * Work around GCC bug causing crashes in Mozilla with SSE2
    560 *
    561 * When using -msse, gcc generates movdqa instructions assuming that
    562 * the stack is 16 byte aligned. Unfortunately some applications, such
    563 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
    564 * causes the movdqa instructions to fail.
    565 *
    566 * The __force_align_arg_pointer__ makes gcc generate a prologue that
    567 * realigns the stack pointer to 16 bytes.
    568 *
    569 * On x86-64 this is not necessary because the standard ABI already
    570 * calls for a 16 byte aligned stack.
    571 *
    572 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
    573 */
    574 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
    575 __attribute__((__force_align_arg_pointer__))
    576 #endif
    577 PIXMAN_EXPORT void
    578 pixman_image_composite32 (pixman_op_t      op,
    579                          pixman_image_t * src,
    580                          pixman_image_t * mask,
    581                          pixman_image_t * dest,
    582                          int32_t          src_x,
    583                          int32_t          src_y,
    584                          int32_t          mask_x,
    585                          int32_t          mask_y,
    586                          int32_t          dest_x,
    587                          int32_t          dest_y,
    588                          int32_t          width,
    589                          int32_t          height)
    590 {
    591    pixman_format_code_t src_format, mask_format, dest_format;
    592    pixman_region32_t region;
    593    pixman_box32_t extents;
    594    pixman_implementation_t *imp;
    595    pixman_composite_func_t func;
    596    pixman_composite_info_t info;
    597    const pixman_box32_t *pbox;
    598    int n;
    599 
    600    _pixman_image_validate (src);
    601    if (mask)
    602 _pixman_image_validate (mask);
    603    _pixman_image_validate (dest);
    604 
    605    src_format = src->common.extended_format_code;
    606    info.src_flags = src->common.flags;
    607 
    608    if (mask && !(mask->common.flags & FAST_PATH_IS_OPAQUE))
    609    {
    610 mask_format = mask->common.extended_format_code;
    611 info.mask_flags = mask->common.flags;
    612    }
    613    else
    614    {
    615 mask_format = PIXMAN_null;
    616 info.mask_flags = FAST_PATH_IS_OPAQUE | FAST_PATH_NO_ALPHA_MAP;
    617    }
    618 
    619    dest_format = dest->common.extended_format_code;
    620    info.dest_flags = dest->common.flags;
    621 
    622    /* Check for pixbufs */
    623    if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
    624 (src->type == BITS && src->bits.bits == mask->bits.bits)	   &&
    625 (src->common.repeat == mask->common.repeat)			   &&
    626 (info.src_flags & info.mask_flags & FAST_PATH_ID_TRANSFORM)	   &&
    627 (src_x == mask_x && src_y == mask_y))
    628    {
    629 if (src_format == PIXMAN_x8b8g8r8)
    630     src_format = mask_format = PIXMAN_pixbuf;
    631 else if (src_format == PIXMAN_x8r8g8b8)
    632     src_format = mask_format = PIXMAN_rpixbuf;
    633    }
    634 
    635    pixman_region32_init (&region);
    636 
    637    if (!_pixman_compute_composite_region32 (
    638     &region, src, mask, dest,
    639     src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
    640    {
    641 goto out;
    642    }
    643 
    644    extents = *pixman_region32_extents (&region);
    645 
    646    extents.x1 -= dest_x - src_x;
    647    extents.y1 -= dest_y - src_y;
    648    extents.x2 -= dest_x - src_x;
    649    extents.y2 -= dest_y - src_y;
    650 
    651    if (!analyze_extent (src, &extents, &info.src_flags))
    652 goto out;
    653 
    654    extents.x1 -= src_x - mask_x;
    655    extents.y1 -= src_y - mask_y;
    656    extents.x2 -= src_x - mask_x;
    657    extents.y2 -= src_y - mask_y;
    658 
    659    if (!analyze_extent (mask, &extents, &info.mask_flags))
    660 goto out;
    661 
    662    /* If the clip is within the source samples, and the samples are
    663     * opaque, then the source is effectively opaque.
    664     */
    665 #define NEAREST_OPAQUE	(FAST_PATH_SAMPLES_OPAQUE |			\
    666 		 FAST_PATH_NEAREST_FILTER |			\
    667 		 FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
    668 #define BILINEAR_OPAQUE	(FAST_PATH_SAMPLES_OPAQUE |			\
    669 		 FAST_PATH_BILINEAR_FILTER |			\
    670 		 FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR)
    671 
    672    if ((info.src_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
    673 (info.src_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
    674    {
    675 info.src_flags |= FAST_PATH_IS_OPAQUE;
    676    }
    677 
    678    if ((info.mask_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
    679 (info.mask_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
    680    {
    681 info.mask_flags |= FAST_PATH_IS_OPAQUE;
    682    }
    683 
    684    /*
    685     * Check if we can replace our operator by a simpler one
    686     * if the src or dest are opaque. The output operator should be
    687     * mathematically equivalent to the source.
    688     */
    689    info.op = optimize_operator (op, info.src_flags, info.mask_flags, info.dest_flags);
    690 
    691    _pixman_implementation_lookup_composite (
    692 get_implementation (), info.op,
    693 src_format, info.src_flags,
    694 mask_format, info.mask_flags,
    695 dest_format, info.dest_flags,
    696 &imp, &func);
    697 
    698    info.src_image = src;
    699    info.mask_image = mask;
    700    info.dest_image = dest;
    701 
    702    pbox = pixman_region32_rectangles (&region, &n);
    703 
    704    while (n--)
    705    {
    706 info.src_x = pbox->x1 + src_x - dest_x;
    707 info.src_y = pbox->y1 + src_y - dest_y;
    708 info.mask_x = pbox->x1 + mask_x - dest_x;
    709 info.mask_y = pbox->y1 + mask_y - dest_y;
    710 info.dest_x = pbox->x1;
    711 info.dest_y = pbox->y1;
    712 info.width = pbox->x2 - pbox->x1;
    713 info.height = pbox->y2 - pbox->y1;
    714 
    715 func (imp, &info);
    716 
    717 pbox++;
    718    }
    719 
    720 out:
    721    pixman_region32_fini (&region);
    722 }
    723 
    724 PIXMAN_EXPORT void
    725 pixman_image_composite (pixman_op_t      op,
    726                        pixman_image_t * src,
    727                        pixman_image_t * mask,
    728                        pixman_image_t * dest,
    729                        int16_t          src_x,
    730                        int16_t          src_y,
    731                        int16_t          mask_x,
    732                        int16_t          mask_y,
    733                        int16_t          dest_x,
    734                        int16_t          dest_y,
    735                        uint16_t         width,
    736                        uint16_t         height)
    737 {
    738    pixman_image_composite32 (op, src, mask, dest, src_x, src_y, 
    739                              mask_x, mask_y, dest_x, dest_y, width, height);
    740 }
    741 
    742 PIXMAN_EXPORT void
    743 pixman_image_composite64f (pixman_op_t      op,
    744                           pixman_image_t * src,
    745                           pixman_image_t * mask,
    746                           pixman_image_t * dest,
    747                           double           src_x,
    748                           double           src_y,
    749                           double           mask_x,
    750                           double           mask_y,
    751                           double           dest_x,
    752                           double           dest_y,
    753                           double           width,
    754                           double           height)
    755 {
    756    pixman_image_composite32 (op, src, mask, dest, src_x, src_y, 
    757                              mask_x, mask_y, dest_x, dest_y, width, height);
    758 }
    759 
    760 PIXMAN_EXPORT pixman_bool_t
    761 pixman_blt (uint32_t *src_bits,
    762            uint32_t *dst_bits,
    763            int       src_stride,
    764            int       dst_stride,
    765            int       src_bpp,
    766            int       dst_bpp,
    767            int       src_x,
    768            int       src_y,
    769            int       dest_x,
    770            int       dest_y,
    771            int       width,
    772            int       height)
    773 {
    774    return _pixman_implementation_blt (get_implementation(),
    775 			       src_bits, dst_bits, src_stride, dst_stride,
    776                                       src_bpp, dst_bpp,
    777                                       src_x, src_y,
    778                                       dest_x, dest_y,
    779                                       width, height);
    780 }
    781 
    782 PIXMAN_EXPORT pixman_bool_t
    783 pixman_fill (uint32_t *bits,
    784             int       stride,
    785             int       bpp,
    786             int       x,
    787             int       y,
    788             int       width,
    789             int       height,
    790             uint32_t  filler)
    791 {
    792    return _pixman_implementation_fill (
    793 get_implementation(), bits, stride, bpp, x, y, width, height, filler);
    794 }
    795 
    796 static uint32_t
    797 color_to_uint32 (const pixman_color_t *color)
    798 {
    799    return
    800        (color->alpha >> 8 << 24) |
    801        (color->red >> 8 << 16) |
    802        (color->green & 0xff00) |
    803        (color->blue >> 8);
    804 }
    805 
    806 static pixman_bool_t
    807 color_to_pixel (const pixman_color_t *color,
    808                uint32_t *            pixel,
    809                pixman_format_code_t  format)
    810 {
    811    uint32_t c = color_to_uint32 (color);
    812 
    813    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA_FLOAT)
    814    {
    815 return FALSE;
    816    }
    817 
    818    if (!(format == PIXMAN_a8r8g8b8     ||
    819          format == PIXMAN_x8r8g8b8     ||
    820          format == PIXMAN_a8b8g8r8     ||
    821          format == PIXMAN_x8b8g8r8     ||
    822          format == PIXMAN_b8g8r8a8     ||
    823          format == PIXMAN_b8g8r8x8     ||
    824          format == PIXMAN_r8g8b8a8     ||
    825          format == PIXMAN_r8g8b8x8     ||
    826          format == PIXMAN_r5g6b5       ||
    827          format == PIXMAN_b5g6r5       ||
    828          format == PIXMAN_a8           ||
    829          format == PIXMAN_a1))
    830    {
    831 return FALSE;
    832    }
    833 
    834    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
    835    {
    836 c = ((c & 0xff000000) >>  0) |
    837     ((c & 0x00ff0000) >> 16) |
    838     ((c & 0x0000ff00) >>  0) |
    839     ((c & 0x000000ff) << 16);
    840    }
    841    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
    842    {
    843 c = ((c & 0xff000000) >> 24) |
    844     ((c & 0x00ff0000) >>  8) |
    845     ((c & 0x0000ff00) <<  8) |
    846     ((c & 0x000000ff) << 24);
    847    }
    848    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA)
    849 c = ((c & 0xff000000) >> 24) | (c << 8);
    850 
    851    if (format == PIXMAN_a1)
    852 c = c >> 31;
    853    else if (format == PIXMAN_a8)
    854 c = c >> 24;
    855    else if (format == PIXMAN_r5g6b5 ||
    856             format == PIXMAN_b5g6r5)
    857 c = convert_8888_to_0565 (c);
    858 
    859 #if 0
    860    printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
    861    printf ("pixel: %x\n", c);
    862 #endif
    863 
    864    *pixel = c;
    865    return TRUE;
    866 }
    867 
    868 PIXMAN_EXPORT pixman_bool_t
    869 pixman_image_fill_rectangles (pixman_op_t                 op,
    870                              pixman_image_t *            dest,
    871 		      const pixman_color_t *      color,
    872                              int                         n_rects,
    873                              const pixman_rectangle16_t *rects)
    874 {
    875    pixman_box32_t stack_boxes[6] = {0};
    876    pixman_box32_t *boxes;
    877    pixman_bool_t result;
    878    int i;
    879 
    880    if (n_rects > 6)
    881    {
    882        boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
    883        if (boxes == NULL)
    884            return FALSE;
    885    }
    886    else
    887    {
    888        boxes = stack_boxes;
    889    }
    890 
    891    for (i = 0; i < n_rects; ++i)
    892    {
    893        boxes[i].x1 = rects[i].x;
    894        boxes[i].y1 = rects[i].y;
    895        boxes[i].x2 = boxes[i].x1 + rects[i].width;
    896        boxes[i].y2 = boxes[i].y1 + rects[i].height;
    897    }
    898 
    899    result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
    900 
    901    if (boxes != stack_boxes)
    902        free (boxes);
    903    
    904    return result;
    905 }
    906 
    907 PIXMAN_EXPORT pixman_bool_t
    908 pixman_image_fill_boxes (pixman_op_t           op,
    909                         pixman_image_t *      dest,
    910                         const pixman_color_t *color,
    911                         int                   n_boxes,
    912                         const pixman_box32_t *boxes)
    913 {
    914    pixman_image_t *solid;
    915    pixman_color_t c;
    916    int i;
    917 
    918    _pixman_image_validate (dest);
    919    
    920    if (color->alpha == 0xffff)
    921    {
    922        if (op == PIXMAN_OP_OVER)
    923            op = PIXMAN_OP_SRC;
    924    }
    925 
    926    if (op == PIXMAN_OP_CLEAR)
    927    {
    928        c.red = 0;
    929        c.green = 0;
    930        c.blue = 0;
    931        c.alpha = 0;
    932 
    933        color = &c;
    934 
    935        op = PIXMAN_OP_SRC;
    936    }
    937 
    938    if (op == PIXMAN_OP_SRC)
    939    {
    940        uint32_t pixel;
    941 
    942        if (color_to_pixel (color, &pixel, dest->bits.format))
    943        {
    944            pixman_region32_t fill_region;
    945            int n_rects, j;
    946            pixman_box32_t *rects;
    947 
    948            if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
    949                return FALSE;
    950 
    951            if (dest->common.have_clip_region)
    952            {
    953                if (!pixman_region32_intersect (&fill_region,
    954                                                &fill_region,
    955                                                &dest->common.clip_region))
    956                    return FALSE;
    957            }
    958 
    959            rects = pixman_region32_rectangles (&fill_region, &n_rects);
    960            for (j = 0; j < n_rects; ++j)
    961            {
    962                const pixman_box32_t *rect = &(rects[j]);
    963                pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
    964                             rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
    965                             pixel);
    966            }
    967 
    968            pixman_region32_fini (&fill_region);
    969            return TRUE;
    970        }
    971    }
    972 
    973    solid = pixman_image_create_solid_fill (color);
    974    if (!solid)
    975        return FALSE;
    976 
    977    for (i = 0; i < n_boxes; ++i)
    978    {
    979        const pixman_box32_t *box = &(boxes[i]);
    980 
    981        pixman_image_composite32 (op, solid, NULL, dest,
    982                                  0, 0, 0, 0,
    983                                  box->x1, box->y1,
    984                                  box->x2 - box->x1, box->y2 - box->y1);
    985    }
    986 
    987    pixman_image_unref (solid);
    988 
    989    return TRUE;
    990 }
    991 
    992 /**
    993 * pixman_version:
    994 *
    995 * Returns the version of the pixman library encoded in a single
    996 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
    997 * later versions compare greater than earlier versions.
    998 *
    999 * A run-time comparison to check that pixman's version is greater than
   1000 * or equal to version X.Y.Z could be performed as follows:
   1001 *
   1002 * <informalexample><programlisting>
   1003 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
   1004 * </programlisting></informalexample>
   1005 *
   1006 * See also pixman_version_string() as well as the compile-time
   1007 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
   1008 *
   1009 * Return value: the encoded version.
   1010 **/
   1011 PIXMAN_EXPORT int
   1012 pixman_version (void)
   1013 {
   1014    return PIXMAN_VERSION;
   1015 }
   1016 
   1017 /**
   1018 * pixman_version_string:
   1019 *
   1020 * Returns the version of the pixman library as a human-readable string
   1021 * of the form "X.Y.Z".
   1022 *
   1023 * See also pixman_version() as well as the compile-time equivalents
   1024 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
   1025 *
   1026 * Return value: a string containing the version.
   1027 **/
   1028 PIXMAN_EXPORT const char*
   1029 pixman_version_string (void)
   1030 {
   1031    return PIXMAN_VERSION_STRING;
   1032 }
   1033 
   1034 /**
   1035 * pixman_format_supported_source:
   1036 * @format: A pixman_format_code_t format
   1037 *
   1038 * Return value: whether the provided format code is a supported
   1039 * format for a pixman surface used as a source in
   1040 * rendering.
   1041 *
   1042 * Currently, all pixman_format_code_t values are supported.
   1043 **/
   1044 PIXMAN_EXPORT pixman_bool_t
   1045 pixman_format_supported_source (pixman_format_code_t format)
   1046 {
   1047    switch (format)
   1048    {
   1049    /* 32 bpp formats */
   1050    case PIXMAN_a2b10g10r10:
   1051    case PIXMAN_x2b10g10r10:
   1052    case PIXMAN_a2r10g10b10:
   1053    case PIXMAN_x2r10g10b10:
   1054    case PIXMAN_a8r8g8b8:
   1055    case PIXMAN_a8r8g8b8_sRGB:
   1056    case PIXMAN_r8g8b8_sRGB:
   1057    case PIXMAN_x8r8g8b8:
   1058    case PIXMAN_a8b8g8r8:
   1059    case PIXMAN_x8b8g8r8:
   1060    case PIXMAN_b8g8r8a8:
   1061    case PIXMAN_b8g8r8x8:
   1062    case PIXMAN_r8g8b8a8:
   1063    case PIXMAN_r8g8b8x8:
   1064    case PIXMAN_r8g8b8:
   1065    case PIXMAN_b8g8r8:
   1066    case PIXMAN_r5g6b5:
   1067    case PIXMAN_b5g6r5:
   1068    case PIXMAN_x14r6g6b6:
   1069    /* 16 bpp formats */
   1070    case PIXMAN_a1r5g5b5:
   1071    case PIXMAN_x1r5g5b5:
   1072    case PIXMAN_a1b5g5r5:
   1073    case PIXMAN_x1b5g5r5:
   1074    case PIXMAN_a4r4g4b4:
   1075    case PIXMAN_x4r4g4b4:
   1076    case PIXMAN_a4b4g4r4:
   1077    case PIXMAN_x4b4g4r4:
   1078    /* 8bpp formats */
   1079    case PIXMAN_a8:
   1080    case PIXMAN_r3g3b2:
   1081    case PIXMAN_b2g3r3:
   1082    case PIXMAN_a2r2g2b2:
   1083    case PIXMAN_a2b2g2r2:
   1084    case PIXMAN_c8:
   1085    case PIXMAN_g8:
   1086    case PIXMAN_x4a4:
   1087    /* Collides with PIXMAN_c8
   1088       case PIXMAN_x4c4:
   1089     */
   1090    /* Collides with PIXMAN_g8
   1091       case PIXMAN_x4g4:
   1092     */
   1093    /* 4bpp formats */
   1094    case PIXMAN_a4:
   1095    case PIXMAN_r1g2b1:
   1096    case PIXMAN_b1g2r1:
   1097    case PIXMAN_a1r1g1b1:
   1098    case PIXMAN_a1b1g1r1:
   1099    case PIXMAN_c4:
   1100    case PIXMAN_g4:
   1101    /* 1bpp formats */
   1102    case PIXMAN_a1:
   1103    case PIXMAN_g1:
   1104    /* YUV formats */
   1105    case PIXMAN_yuy2:
   1106    case PIXMAN_yv12:
   1107 return TRUE;
   1108 
   1109    default:
   1110 return FALSE;
   1111    }
   1112 }
   1113 
   1114 /**
   1115 * pixman_format_supported_destination:
   1116 * @format: A pixman_format_code_t format
   1117 *
   1118 * Return value: whether the provided format code is a supported
   1119 * format for a pixman surface used as a destination in
   1120 * rendering.
   1121 *
   1122 * Currently, all pixman_format_code_t values are supported
   1123 * except for the YUV formats.
   1124 **/
   1125 PIXMAN_EXPORT pixman_bool_t
   1126 pixman_format_supported_destination (pixman_format_code_t format)
   1127 {
   1128    /* YUV formats cannot be written to at the moment */
   1129    if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
   1130 return FALSE;
   1131 
   1132    return pixman_format_supported_source (format);
   1133 }
   1134 
   1135 PIXMAN_EXPORT pixman_bool_t
   1136 pixman_compute_composite_region (pixman_region16_t * region,
   1137                                 pixman_image_t *    src_image,
   1138                                 pixman_image_t *    mask_image,
   1139                                 pixman_image_t *    dest_image,
   1140                                 int16_t             src_x,
   1141                                 int16_t             src_y,
   1142                                 int16_t             mask_x,
   1143                                 int16_t             mask_y,
   1144                                 int16_t             dest_x,
   1145                                 int16_t             dest_y,
   1146                                 uint16_t            width,
   1147                                 uint16_t            height)
   1148 {
   1149    pixman_region32_t r32;
   1150    pixman_bool_t retval;
   1151 
   1152    pixman_region32_init (&r32);
   1153 
   1154    retval = _pixman_compute_composite_region32 (
   1155 &r32, src_image, mask_image, dest_image,
   1156 src_x, src_y, mask_x, mask_y, dest_x, dest_y,
   1157 width, height);
   1158 
   1159    if (retval)
   1160    {
   1161 if (!pixman_region16_copy_from_region32 (region, &r32))
   1162     retval = FALSE;
   1163    }
   1164 
   1165    pixman_region32_fini (&r32);
   1166    return retval;
   1167 }