gfx/cairo/libpixman/src/pixman.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/libpixman/src/pixman.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1135 @@
     1.4 +/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
     1.5 +/*
     1.6 + * Copyright © 2000 SuSE, Inc.
     1.7 + * Copyright © 2007 Red Hat, Inc.
     1.8 + *
     1.9 + * Permission to use, copy, modify, distribute, and sell this software and its
    1.10 + * documentation for any purpose is hereby granted without fee, provided that
    1.11 + * the above copyright notice appear in all copies and that both that
    1.12 + * copyright notice and this permission notice appear in supporting
    1.13 + * documentation, and that the name of SuSE not be used in advertising or
    1.14 + * publicity pertaining to distribution of the software without specific,
    1.15 + * written prior permission.  SuSE makes no representations about the
    1.16 + * suitability of this software for any purpose.  It is provided "as is"
    1.17 + * without express or implied warranty.
    1.18 + *
    1.19 + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
    1.20 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
    1.21 + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    1.22 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
    1.23 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
    1.24 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    1.25 + *
    1.26 + * Author:  Keith Packard, SuSE, Inc.
    1.27 + */
    1.28 +
    1.29 +#ifdef HAVE_CONFIG_H
    1.30 +#include <config.h>
    1.31 +#endif
    1.32 +#include "pixman-private.h"
    1.33 +
    1.34 +#include <stdlib.h>
    1.35 +
    1.36 +pixman_implementation_t *global_implementation;
    1.37 +
    1.38 +#ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
    1.39 +static void __attribute__((constructor))
    1.40 +pixman_constructor (void)
    1.41 +{
    1.42 +    global_implementation = _pixman_choose_implementation ();
    1.43 +}
    1.44 +#endif
    1.45 +
    1.46 +typedef struct operator_info_t operator_info_t;
    1.47 +
    1.48 +struct operator_info_t
    1.49 +{
    1.50 +    uint8_t	opaque_info[4];
    1.51 +};
    1.52 +
    1.53 +#define PACK(neither, src, dest, both)			\
    1.54 +    {{	    (uint8_t)PIXMAN_OP_ ## neither,		\
    1.55 +	    (uint8_t)PIXMAN_OP_ ## src,			\
    1.56 +	    (uint8_t)PIXMAN_OP_ ## dest,		\
    1.57 +	    (uint8_t)PIXMAN_OP_ ## both		}}
    1.58 +
    1.59 +static const operator_info_t operator_table[] =
    1.60 +{
    1.61 +    /*    Neither Opaque         Src Opaque             Dst Opaque             Both Opaque */
    1.62 +    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
    1.63 +    PACK (SRC,                   SRC,                   SRC,                   SRC),
    1.64 +    PACK (DST,                   DST,                   DST,                   DST),
    1.65 +    PACK (OVER,                  SRC,                   OVER,                  SRC),
    1.66 +    PACK (OVER_REVERSE,          OVER_REVERSE,          DST,                   DST),
    1.67 +    PACK (IN,                    IN,                    SRC,                   SRC),
    1.68 +    PACK (IN_REVERSE,            DST,                   IN_REVERSE,            DST),
    1.69 +    PACK (OUT,                   OUT,                   CLEAR,                 CLEAR),
    1.70 +    PACK (OUT_REVERSE,           CLEAR,                 OUT_REVERSE,           CLEAR),
    1.71 +    PACK (ATOP,                  IN,                    OVER,                  SRC),
    1.72 +    PACK (ATOP_REVERSE,          OVER_REVERSE,          IN_REVERSE,            DST),
    1.73 +    PACK (XOR,                   OUT,                   OUT_REVERSE,           CLEAR),
    1.74 +    PACK (ADD,                   ADD,                   ADD,                   ADD),
    1.75 +    PACK (SATURATE,              OVER_REVERSE,          DST,                   DST),
    1.76 +
    1.77 +    {{ 0 /* 0x0e */ }},
    1.78 +    {{ 0 /* 0x0f */ }},
    1.79 +
    1.80 +    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
    1.81 +    PACK (SRC,                   SRC,                   SRC,                   SRC),
    1.82 +    PACK (DST,                   DST,                   DST,                   DST),
    1.83 +    PACK (DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER),
    1.84 +    PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE),
    1.85 +    PACK (DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN),
    1.86 +    PACK (DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE),
    1.87 +    PACK (DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT),
    1.88 +    PACK (DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE),
    1.89 +    PACK (DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP),
    1.90 +    PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE),
    1.91 +    PACK (DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR),
    1.92 +
    1.93 +    {{ 0 /* 0x1c */ }},
    1.94 +    {{ 0 /* 0x1d */ }},
    1.95 +    {{ 0 /* 0x1e */ }},
    1.96 +    {{ 0 /* 0x1f */ }},
    1.97 +
    1.98 +    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
    1.99 +    PACK (SRC,                   SRC,                   SRC,                   SRC),
   1.100 +    PACK (DST,                   DST,                   DST,                   DST),
   1.101 +    PACK (CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER),
   1.102 +    PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE),
   1.103 +    PACK (CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN),
   1.104 +    PACK (CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE),
   1.105 +    PACK (CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT),
   1.106 +    PACK (CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE),
   1.107 +    PACK (CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP),
   1.108 +    PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE),
   1.109 +    PACK (CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR),
   1.110 +
   1.111 +    {{ 0 /* 0x2c */ }},
   1.112 +    {{ 0 /* 0x2d */ }},
   1.113 +    {{ 0 /* 0x2e */ }},
   1.114 +    {{ 0 /* 0x2f */ }},
   1.115 +
   1.116 +    PACK (MULTIPLY,              MULTIPLY,              MULTIPLY,              MULTIPLY),
   1.117 +    PACK (SCREEN,                SCREEN,                SCREEN,                SCREEN),
   1.118 +    PACK (OVERLAY,               OVERLAY,               OVERLAY,               OVERLAY),
   1.119 +    PACK (DARKEN,                DARKEN,                DARKEN,                DARKEN),
   1.120 +    PACK (LIGHTEN,               LIGHTEN,               LIGHTEN,               LIGHTEN),
   1.121 +    PACK (COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE),
   1.122 +    PACK (COLOR_BURN,            COLOR_BURN,            COLOR_BURN,            COLOR_BURN),
   1.123 +    PACK (HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT),
   1.124 +    PACK (SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT),
   1.125 +    PACK (DIFFERENCE,            DIFFERENCE,            DIFFERENCE,            DIFFERENCE),
   1.126 +    PACK (EXCLUSION,             EXCLUSION,             EXCLUSION,             EXCLUSION),
   1.127 +    PACK (HSL_HUE,               HSL_HUE,               HSL_HUE,               HSL_HUE),
   1.128 +    PACK (HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION),
   1.129 +    PACK (HSL_COLOR,             HSL_COLOR,             HSL_COLOR,             HSL_COLOR),
   1.130 +    PACK (HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY),
   1.131 +};
   1.132 +
   1.133 +/*
   1.134 + * Optimize the current operator based on opacity of source or destination
   1.135 + * The output operator should be mathematically equivalent to the source.
   1.136 + */
   1.137 +static pixman_op_t
   1.138 +optimize_operator (pixman_op_t     op,
   1.139 +		   uint32_t        src_flags,
   1.140 +		   uint32_t        mask_flags,
   1.141 +		   uint32_t        dst_flags)
   1.142 +{
   1.143 +    pixman_bool_t is_source_opaque, is_dest_opaque;
   1.144 +
   1.145 +#define OPAQUE_SHIFT 13
   1.146 +    
   1.147 +    COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT));
   1.148 +    
   1.149 +    is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE);
   1.150 +    is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE);
   1.151 +
   1.152 +    is_dest_opaque >>= OPAQUE_SHIFT - 1;
   1.153 +    is_source_opaque >>= OPAQUE_SHIFT;
   1.154 +
   1.155 +    return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
   1.156 +}
   1.157 +
   1.158 +/*
   1.159 + * Computing composite region
   1.160 + */
   1.161 +static inline pixman_bool_t
   1.162 +clip_general_image (pixman_region32_t * region,
   1.163 +                    pixman_region32_t * clip,
   1.164 +                    int                 dx,
   1.165 +                    int                 dy)
   1.166 +{
   1.167 +    if (pixman_region32_n_rects (region) == 1 &&
   1.168 +        pixman_region32_n_rects (clip) == 1)
   1.169 +    {
   1.170 +	pixman_box32_t *  rbox = pixman_region32_rectangles (region, NULL);
   1.171 +	pixman_box32_t *  cbox = pixman_region32_rectangles (clip, NULL);
   1.172 +	int v;
   1.173 +
   1.174 +	if (rbox->x1 < (v = cbox->x1 + dx))
   1.175 +	    rbox->x1 = v;
   1.176 +	if (rbox->x2 > (v = cbox->x2 + dx))
   1.177 +	    rbox->x2 = v;
   1.178 +	if (rbox->y1 < (v = cbox->y1 + dy))
   1.179 +	    rbox->y1 = v;
   1.180 +	if (rbox->y2 > (v = cbox->y2 + dy))
   1.181 +	    rbox->y2 = v;
   1.182 +	if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
   1.183 +	{
   1.184 +	    pixman_region32_init (region);
   1.185 +	    return FALSE;
   1.186 +	}
   1.187 +    }
   1.188 +    else if (!pixman_region32_not_empty (clip))
   1.189 +    {
   1.190 +	return FALSE;
   1.191 +    }
   1.192 +    else
   1.193 +    {
   1.194 +	if (dx || dy)
   1.195 +	    pixman_region32_translate (region, -dx, -dy);
   1.196 +
   1.197 +	if (!pixman_region32_intersect (region, region, clip))
   1.198 +	    return FALSE;
   1.199 +
   1.200 +	if (dx || dy)
   1.201 +	    pixman_region32_translate (region, dx, dy);
   1.202 +    }
   1.203 +
   1.204 +    return pixman_region32_not_empty (region);
   1.205 +}
   1.206 +
   1.207 +static inline pixman_bool_t
   1.208 +clip_source_image (pixman_region32_t * region,
   1.209 +                   pixman_image_t *    image,
   1.210 +                   int                 dx,
   1.211 +                   int                 dy)
   1.212 +{
   1.213 +    /* Source clips are ignored, unless they are explicitly turned on
   1.214 +     * and the clip in question was set by an X client. (Because if
   1.215 +     * the clip was not set by a client, then it is a hierarchy
   1.216 +     * clip and those should always be ignored for sources).
   1.217 +     */
   1.218 +    if (!image->common.clip_sources || !image->common.client_clip)
   1.219 +	return TRUE;
   1.220 +
   1.221 +    return clip_general_image (region,
   1.222 +                               &image->common.clip_region,
   1.223 +                               dx, dy);
   1.224 +}
   1.225 +
   1.226 +/*
   1.227 + * returns FALSE if the final region is empty.  Indistinguishable from
   1.228 + * an allocation failure, but rendering ignores those anyways.
   1.229 + */
   1.230 +pixman_bool_t
   1.231 +_pixman_compute_composite_region32 (pixman_region32_t * region,
   1.232 +				    pixman_image_t *    src_image,
   1.233 +				    pixman_image_t *    mask_image,
   1.234 +				    pixman_image_t *    dest_image,
   1.235 +				    int32_t             src_x,
   1.236 +				    int32_t             src_y,
   1.237 +				    int32_t             mask_x,
   1.238 +				    int32_t             mask_y,
   1.239 +				    int32_t             dest_x,
   1.240 +				    int32_t             dest_y,
   1.241 +				    int32_t             width,
   1.242 +				    int32_t             height)
   1.243 +{
   1.244 +    region->extents.x1 = dest_x;
   1.245 +    region->extents.x2 = dest_x + width;
   1.246 +    region->extents.y1 = dest_y;
   1.247 +    region->extents.y2 = dest_y + height;
   1.248 +
   1.249 +    region->extents.x1 = MAX (region->extents.x1, 0);
   1.250 +    region->extents.y1 = MAX (region->extents.y1, 0);
   1.251 +    region->extents.x2 = MIN (region->extents.x2, dest_image->bits.width);
   1.252 +    region->extents.y2 = MIN (region->extents.y2, dest_image->bits.height);
   1.253 +
   1.254 +    region->data = 0;
   1.255 +
   1.256 +    /* Check for empty operation */
   1.257 +    if (region->extents.x1 >= region->extents.x2 ||
   1.258 +        region->extents.y1 >= region->extents.y2)
   1.259 +    {
   1.260 +	region->extents.x1 = 0;
   1.261 +	region->extents.x2 = 0;
   1.262 +	region->extents.y1 = 0;
   1.263 +	region->extents.y2 = 0;
   1.264 +	return FALSE;
   1.265 +    }
   1.266 +
   1.267 +    if (dest_image->common.have_clip_region)
   1.268 +    {
   1.269 +	if (!clip_general_image (region, &dest_image->common.clip_region, 0, 0))
   1.270 +	    return FALSE;
   1.271 +    }
   1.272 +
   1.273 +    if (dest_image->common.alpha_map)
   1.274 +    {
   1.275 +	if (!pixman_region32_intersect_rect (region, region,
   1.276 +					     dest_image->common.alpha_origin_x,
   1.277 +					     dest_image->common.alpha_origin_y,
   1.278 +					     dest_image->common.alpha_map->width,
   1.279 +					     dest_image->common.alpha_map->height))
   1.280 +	{
   1.281 +	    return FALSE;
   1.282 +	}
   1.283 +	if (!pixman_region32_not_empty (region))
   1.284 +	    return FALSE;
   1.285 +	if (dest_image->common.alpha_map->common.have_clip_region)
   1.286 +	{
   1.287 +	    if (!clip_general_image (region, &dest_image->common.alpha_map->common.clip_region,
   1.288 +				     -dest_image->common.alpha_origin_x,
   1.289 +				     -dest_image->common.alpha_origin_y))
   1.290 +	    {
   1.291 +		return FALSE;
   1.292 +	    }
   1.293 +	}
   1.294 +    }
   1.295 +
   1.296 +    /* clip against src */
   1.297 +    if (src_image->common.have_clip_region)
   1.298 +    {
   1.299 +	if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
   1.300 +	    return FALSE;
   1.301 +    }
   1.302 +    if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
   1.303 +    {
   1.304 +	if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
   1.305 +	                        dest_x - (src_x - src_image->common.alpha_origin_x),
   1.306 +	                        dest_y - (src_y - src_image->common.alpha_origin_y)))
   1.307 +	{
   1.308 +	    return FALSE;
   1.309 +	}
   1.310 +    }
   1.311 +    /* clip against mask */
   1.312 +    if (mask_image && mask_image->common.have_clip_region)
   1.313 +    {
   1.314 +	if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
   1.315 +	    return FALSE;
   1.316 +
   1.317 +	if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
   1.318 +	{
   1.319 +	    if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
   1.320 +	                            dest_x - (mask_x - mask_image->common.alpha_origin_x),
   1.321 +	                            dest_y - (mask_y - mask_image->common.alpha_origin_y)))
   1.322 +	    {
   1.323 +		return FALSE;
   1.324 +	    }
   1.325 +	}
   1.326 +    }
   1.327 +
   1.328 +    return TRUE;
   1.329 +}
   1.330 +
   1.331 +typedef struct
   1.332 +{
   1.333 +    pixman_fixed_48_16_t	x1;
   1.334 +    pixman_fixed_48_16_t	y1;
   1.335 +    pixman_fixed_48_16_t	x2;
   1.336 +    pixman_fixed_48_16_t	y2;
   1.337 +} box_48_16_t;
   1.338 +
   1.339 +static pixman_bool_t
   1.340 +compute_transformed_extents (pixman_transform_t *transform,
   1.341 +			     const pixman_box32_t *extents,
   1.342 +			     box_48_16_t *transformed)
   1.343 +{
   1.344 +    pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
   1.345 +    pixman_fixed_t x1, y1, x2, y2;
   1.346 +    int i;
   1.347 +
   1.348 +    x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2;
   1.349 +    y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2;
   1.350 +    x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2;
   1.351 +    y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2;
   1.352 +
   1.353 +    if (!transform)
   1.354 +    {
   1.355 +	transformed->x1 = x1;
   1.356 +	transformed->y1 = y1;
   1.357 +	transformed->x2 = x2;
   1.358 +	transformed->y2 = y2;
   1.359 +
   1.360 +	return TRUE;
   1.361 +    }
   1.362 +
   1.363 +    tx1 = ty1 = INT64_MAX;
   1.364 +    tx2 = ty2 = INT64_MIN;
   1.365 +
   1.366 +    for (i = 0; i < 4; ++i)
   1.367 +    {
   1.368 +	pixman_fixed_48_16_t tx, ty;
   1.369 +	pixman_vector_t v;
   1.370 +
   1.371 +	v.vector[0] = (i & 0x01)? x1 : x2;
   1.372 +	v.vector[1] = (i & 0x02)? y1 : y2;
   1.373 +	v.vector[2] = pixman_fixed_1;
   1.374 +
   1.375 +	if (!pixman_transform_point (transform, &v))
   1.376 +	    return FALSE;
   1.377 +
   1.378 +	tx = (pixman_fixed_48_16_t)v.vector[0];
   1.379 +	ty = (pixman_fixed_48_16_t)v.vector[1];
   1.380 +
   1.381 +	if (tx < tx1)
   1.382 +	    tx1 = tx;
   1.383 +	if (ty < ty1)
   1.384 +	    ty1 = ty;
   1.385 +	if (tx > tx2)
   1.386 +	    tx2 = tx;
   1.387 +	if (ty > ty2)
   1.388 +	    ty2 = ty;
   1.389 +    }
   1.390 +
   1.391 +    transformed->x1 = tx1;
   1.392 +    transformed->y1 = ty1;
   1.393 +    transformed->x2 = tx2;
   1.394 +    transformed->y2 = ty2;
   1.395 +
   1.396 +    return TRUE;
   1.397 +}
   1.398 +
   1.399 +#define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
   1.400 +#define ABS(f)      (((f) < 0)?  (-(f)) : (f))
   1.401 +#define IS_16_16(f) (((f) >= pixman_min_fixed_48_16 && ((f) <= pixman_max_fixed_48_16)))
   1.402 +
   1.403 +static pixman_bool_t
   1.404 +analyze_extent (pixman_image_t       *image,
   1.405 +		const pixman_box32_t *extents,
   1.406 +		uint32_t             *flags)
   1.407 +{
   1.408 +    pixman_transform_t *transform;
   1.409 +    pixman_fixed_t x_off, y_off;
   1.410 +    pixman_fixed_t width, height;
   1.411 +    pixman_fixed_t *params;
   1.412 +    box_48_16_t transformed;
   1.413 +    pixman_box32_t exp_extents;
   1.414 +
   1.415 +    if (!image)
   1.416 +	return TRUE;
   1.417 +
   1.418 +    /* Some compositing functions walk one step
   1.419 +     * outside the destination rectangle, so we
   1.420 +     * check here that the expanded-by-one source
   1.421 +     * extents in destination space fits in 16 bits
   1.422 +     */
   1.423 +    if (!IS_16BIT (extents->x1 - 1)		||
   1.424 +	!IS_16BIT (extents->y1 - 1)		||
   1.425 +	!IS_16BIT (extents->x2 + 1)		||
   1.426 +	!IS_16BIT (extents->y2 + 1))
   1.427 +    {
   1.428 +	return FALSE;
   1.429 +    }
   1.430 +
   1.431 +    transform = image->common.transform;
   1.432 +    if (image->common.type == BITS)
   1.433 +    {
   1.434 +	/* During repeat mode calculations we might convert the
   1.435 +	 * width/height of an image to fixed 16.16, so we need
   1.436 +	 * them to be smaller than 16 bits.
   1.437 +	 */
   1.438 +	if (image->bits.width >= 0x7fff	|| image->bits.height >= 0x7fff)
   1.439 +	    return FALSE;
   1.440 +
   1.441 +	if ((image->common.flags & FAST_PATH_ID_TRANSFORM) == FAST_PATH_ID_TRANSFORM &&
   1.442 +	    extents->x1 >= 0 &&
   1.443 +	    extents->y1 >= 0 &&
   1.444 +	    extents->x2 <= image->bits.width &&
   1.445 +	    extents->y2 <= image->bits.height)
   1.446 +	{
   1.447 +	    *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
   1.448 +	    return TRUE;
   1.449 +	}
   1.450 +
   1.451 +	switch (image->common.filter)
   1.452 +	{
   1.453 +	case PIXMAN_FILTER_CONVOLUTION:
   1.454 +	    params = image->common.filter_params;
   1.455 +	    x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
   1.456 +	    y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
   1.457 +	    width = params[0];
   1.458 +	    height = params[1];
   1.459 +	    break;
   1.460 +
   1.461 +	case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
   1.462 +	    params = image->common.filter_params;
   1.463 +	    x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
   1.464 +	    y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
   1.465 +	    width = params[0];
   1.466 +	    height = params[1];
   1.467 +	    break;
   1.468 +	    
   1.469 +	case PIXMAN_FILTER_GOOD:
   1.470 +	case PIXMAN_FILTER_BEST:
   1.471 +	case PIXMAN_FILTER_BILINEAR:
   1.472 +	    x_off = - pixman_fixed_1 / 2;
   1.473 +	    y_off = - pixman_fixed_1 / 2;
   1.474 +	    width = pixman_fixed_1;
   1.475 +	    height = pixman_fixed_1;
   1.476 +	    break;
   1.477 +
   1.478 +	case PIXMAN_FILTER_FAST:
   1.479 +	case PIXMAN_FILTER_NEAREST:
   1.480 +	    x_off = - pixman_fixed_e;
   1.481 +	    y_off = - pixman_fixed_e;
   1.482 +	    width = 0;
   1.483 +	    height = 0;
   1.484 +	    break;
   1.485 +
   1.486 +	default:
   1.487 +	    return FALSE;
   1.488 +	}
   1.489 +    }
   1.490 +    else
   1.491 +    {
   1.492 +	x_off = 0;
   1.493 +	y_off = 0;
   1.494 +	width = 0;
   1.495 +	height = 0;
   1.496 +    }
   1.497 +
   1.498 +    if (!compute_transformed_extents (transform, extents, &transformed))
   1.499 +	return FALSE;
   1.500 +
   1.501 +    /* Expand the source area by a tiny bit so account of different rounding that
   1.502 +     * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
   1.503 +     * 0.5 so this won't cause the area computed to be overly pessimistic.
   1.504 +     */
   1.505 +    transformed.x1 -= 8 * pixman_fixed_e;
   1.506 +    transformed.y1 -= 8 * pixman_fixed_e;
   1.507 +    transformed.x2 += 8 * pixman_fixed_e;
   1.508 +    transformed.y2 += 8 * pixman_fixed_e;
   1.509 +
   1.510 +    if (image->common.type == BITS)
   1.511 +    {
   1.512 +	if (pixman_fixed_to_int (transformed.x1) >= 0			&&
   1.513 +	    pixman_fixed_to_int (transformed.y1) >= 0			&&
   1.514 +	    pixman_fixed_to_int (transformed.x2) < image->bits.width	&&
   1.515 +	    pixman_fixed_to_int (transformed.y2) < image->bits.height)
   1.516 +	{
   1.517 +	    *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
   1.518 +	}
   1.519 +
   1.520 +	if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_1 / 2) >= 0		  &&
   1.521 +	    pixman_fixed_to_int (transformed.y1 - pixman_fixed_1 / 2) >= 0		  &&
   1.522 +	    pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2) < image->bits.width &&
   1.523 +	    pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2) < image->bits.height)
   1.524 +	{
   1.525 +	    *flags |= FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR;
   1.526 +	}
   1.527 +    }
   1.528 +
   1.529 +    /* Check we don't overflow when the destination extents are expanded by one.
   1.530 +     * This ensures that compositing functions can simply walk the source space
   1.531 +     * using 16.16 variables without worrying about overflow.
   1.532 +     */
   1.533 +    exp_extents = *extents;
   1.534 +    exp_extents.x1 -= 1;
   1.535 +    exp_extents.y1 -= 1;
   1.536 +    exp_extents.x2 += 1;
   1.537 +    exp_extents.y2 += 1;
   1.538 +
   1.539 +    if (!compute_transformed_extents (transform, &exp_extents, &transformed))
   1.540 +	return FALSE;
   1.541 +    
   1.542 +    if (!IS_16_16 (transformed.x1 + x_off - 8 * pixman_fixed_e)	||
   1.543 +	!IS_16_16 (transformed.y1 + y_off - 8 * pixman_fixed_e)	||
   1.544 +	!IS_16_16 (transformed.x2 + x_off + 8 * pixman_fixed_e + width)	||
   1.545 +	!IS_16_16 (transformed.y2 + y_off + 8 * pixman_fixed_e + height))
   1.546 +    {
   1.547 +	return FALSE;
   1.548 +    }
   1.549 +
   1.550 +    return TRUE;
   1.551 +}
   1.552 +
   1.553 +/*
   1.554 + * Work around GCC bug causing crashes in Mozilla with SSE2
   1.555 + *
   1.556 + * When using -msse, gcc generates movdqa instructions assuming that
   1.557 + * the stack is 16 byte aligned. Unfortunately some applications, such
   1.558 + * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
   1.559 + * causes the movdqa instructions to fail.
   1.560 + *
   1.561 + * The __force_align_arg_pointer__ makes gcc generate a prologue that
   1.562 + * realigns the stack pointer to 16 bytes.
   1.563 + *
   1.564 + * On x86-64 this is not necessary because the standard ABI already
   1.565 + * calls for a 16 byte aligned stack.
   1.566 + *
   1.567 + * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
   1.568 + */
   1.569 +#if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
   1.570 +__attribute__((__force_align_arg_pointer__))
   1.571 +#endif
   1.572 +PIXMAN_EXPORT void
   1.573 +pixman_image_composite32 (pixman_op_t      op,
   1.574 +                          pixman_image_t * src,
   1.575 +                          pixman_image_t * mask,
   1.576 +                          pixman_image_t * dest,
   1.577 +                          int32_t          src_x,
   1.578 +                          int32_t          src_y,
   1.579 +                          int32_t          mask_x,
   1.580 +                          int32_t          mask_y,
   1.581 +                          int32_t          dest_x,
   1.582 +                          int32_t          dest_y,
   1.583 +                          int32_t          width,
   1.584 +                          int32_t          height)
   1.585 +{
   1.586 +    pixman_format_code_t src_format, mask_format, dest_format;
   1.587 +    pixman_region32_t region;
   1.588 +    pixman_box32_t extents;
   1.589 +    pixman_implementation_t *imp;
   1.590 +    pixman_composite_func_t func;
   1.591 +    pixman_composite_info_t info;
   1.592 +    const pixman_box32_t *pbox;
   1.593 +    int n;
   1.594 +
   1.595 +    _pixman_image_validate (src);
   1.596 +    if (mask)
   1.597 +	_pixman_image_validate (mask);
   1.598 +    _pixman_image_validate (dest);
   1.599 +
   1.600 +    src_format = src->common.extended_format_code;
   1.601 +    info.src_flags = src->common.flags;
   1.602 +
   1.603 +    if (mask && !(mask->common.flags & FAST_PATH_IS_OPAQUE))
   1.604 +    {
   1.605 +	mask_format = mask->common.extended_format_code;
   1.606 +	info.mask_flags = mask->common.flags;
   1.607 +    }
   1.608 +    else
   1.609 +    {
   1.610 +	mask_format = PIXMAN_null;
   1.611 +	info.mask_flags = FAST_PATH_IS_OPAQUE;
   1.612 +    }
   1.613 +
   1.614 +    dest_format = dest->common.extended_format_code;
   1.615 +    info.dest_flags = dest->common.flags;
   1.616 +
   1.617 +    /* Check for pixbufs */
   1.618 +    if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
   1.619 +	(src->type == BITS && src->bits.bits == mask->bits.bits)	   &&
   1.620 +	(src->common.repeat == mask->common.repeat)			   &&
   1.621 +	(info.src_flags & info.mask_flags & FAST_PATH_ID_TRANSFORM)	   &&
   1.622 +	(src_x == mask_x && src_y == mask_y))
   1.623 +    {
   1.624 +	if (src_format == PIXMAN_x8b8g8r8)
   1.625 +	    src_format = mask_format = PIXMAN_pixbuf;
   1.626 +	else if (src_format == PIXMAN_x8r8g8b8)
   1.627 +	    src_format = mask_format = PIXMAN_rpixbuf;
   1.628 +    }
   1.629 +
   1.630 +    pixman_region32_init (&region);
   1.631 +
   1.632 +    if (!_pixman_compute_composite_region32 (
   1.633 +	    &region, src, mask, dest,
   1.634 +	    src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
   1.635 +    {
   1.636 +	goto out;
   1.637 +    }
   1.638 +
   1.639 +    extents = *pixman_region32_extents (&region);
   1.640 +
   1.641 +    extents.x1 -= dest_x - src_x;
   1.642 +    extents.y1 -= dest_y - src_y;
   1.643 +    extents.x2 -= dest_x - src_x;
   1.644 +    extents.y2 -= dest_y - src_y;
   1.645 +
   1.646 +    if (!analyze_extent (src, &extents, &info.src_flags))
   1.647 +	goto out;
   1.648 +
   1.649 +    extents.x1 -= src_x - mask_x;
   1.650 +    extents.y1 -= src_y - mask_y;
   1.651 +    extents.x2 -= src_x - mask_x;
   1.652 +    extents.y2 -= src_y - mask_y;
   1.653 +
   1.654 +    if (!analyze_extent (mask, &extents, &info.mask_flags))
   1.655 +	goto out;
   1.656 +
   1.657 +    /* If the clip is within the source samples, and the samples are
   1.658 +     * opaque, then the source is effectively opaque.
   1.659 +     */
   1.660 +#define NEAREST_OPAQUE	(FAST_PATH_SAMPLES_OPAQUE |			\
   1.661 +			 FAST_PATH_NEAREST_FILTER |			\
   1.662 +			 FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
   1.663 +#define BILINEAR_OPAQUE	(FAST_PATH_SAMPLES_OPAQUE |			\
   1.664 +			 FAST_PATH_BILINEAR_FILTER |			\
   1.665 +			 FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR)
   1.666 +
   1.667 +    if ((info.src_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
   1.668 +	(info.src_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
   1.669 +    {
   1.670 +	info.src_flags |= FAST_PATH_IS_OPAQUE;
   1.671 +    }
   1.672 +
   1.673 +    if ((info.mask_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
   1.674 +	(info.mask_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
   1.675 +    {
   1.676 +	info.mask_flags |= FAST_PATH_IS_OPAQUE;
   1.677 +    }
   1.678 +
   1.679 +    /*
   1.680 +     * Check if we can replace our operator by a simpler one
   1.681 +     * if the src or dest are opaque. The output operator should be
   1.682 +     * mathematically equivalent to the source.
   1.683 +     */
   1.684 +    info.op = optimize_operator (op, info.src_flags, info.mask_flags, info.dest_flags);
   1.685 +
   1.686 +    _pixman_implementation_lookup_composite (
   1.687 +	get_implementation (), info.op,
   1.688 +	src_format, info.src_flags,
   1.689 +	mask_format, info.mask_flags,
   1.690 +	dest_format, info.dest_flags,
   1.691 +	&imp, &func);
   1.692 +
   1.693 +    info.src_image = src;
   1.694 +    info.mask_image = mask;
   1.695 +    info.dest_image = dest;
   1.696 +
   1.697 +    pbox = pixman_region32_rectangles (&region, &n);
   1.698 +
   1.699 +    while (n--)
   1.700 +    {
   1.701 +	info.src_x = pbox->x1 + src_x - dest_x;
   1.702 +	info.src_y = pbox->y1 + src_y - dest_y;
   1.703 +	info.mask_x = pbox->x1 + mask_x - dest_x;
   1.704 +	info.mask_y = pbox->y1 + mask_y - dest_y;
   1.705 +	info.dest_x = pbox->x1;
   1.706 +	info.dest_y = pbox->y1;
   1.707 +	info.width = pbox->x2 - pbox->x1;
   1.708 +	info.height = pbox->y2 - pbox->y1;
   1.709 +
   1.710 +	func (imp, &info);
   1.711 +
   1.712 +	pbox++;
   1.713 +    }
   1.714 +
   1.715 +out:
   1.716 +    pixman_region32_fini (&region);
   1.717 +}
   1.718 +
   1.719 +PIXMAN_EXPORT void
   1.720 +pixman_image_composite (pixman_op_t      op,
   1.721 +                        pixman_image_t * src,
   1.722 +                        pixman_image_t * mask,
   1.723 +                        pixman_image_t * dest,
   1.724 +                        int16_t          src_x,
   1.725 +                        int16_t          src_y,
   1.726 +                        int16_t          mask_x,
   1.727 +                        int16_t          mask_y,
   1.728 +                        int16_t          dest_x,
   1.729 +                        int16_t          dest_y,
   1.730 +                        uint16_t         width,
   1.731 +                        uint16_t         height)
   1.732 +{
   1.733 +    pixman_image_composite32 (op, src, mask, dest, src_x, src_y, 
   1.734 +                              mask_x, mask_y, dest_x, dest_y, width, height);
   1.735 +}
   1.736 +
   1.737 +PIXMAN_EXPORT pixman_bool_t
   1.738 +pixman_blt (uint32_t *src_bits,
   1.739 +            uint32_t *dst_bits,
   1.740 +            int       src_stride,
   1.741 +            int       dst_stride,
   1.742 +            int       src_bpp,
   1.743 +            int       dst_bpp,
   1.744 +            int       src_x,
   1.745 +            int       src_y,
   1.746 +            int       dest_x,
   1.747 +            int       dest_y,
   1.748 +            int       width,
   1.749 +            int       height)
   1.750 +{
   1.751 +    return _pixman_implementation_blt (get_implementation(),
   1.752 +				       src_bits, dst_bits, src_stride, dst_stride,
   1.753 +                                       src_bpp, dst_bpp,
   1.754 +                                       src_x, src_y,
   1.755 +                                       dest_x, dest_y,
   1.756 +                                       width, height);
   1.757 +}
   1.758 +
   1.759 +PIXMAN_EXPORT pixman_bool_t
   1.760 +pixman_fill (uint32_t *bits,
   1.761 +             int       stride,
   1.762 +             int       bpp,
   1.763 +             int       x,
   1.764 +             int       y,
   1.765 +             int       width,
   1.766 +             int       height,
   1.767 +             uint32_t  filler)
   1.768 +{
   1.769 +    return _pixman_implementation_fill (
   1.770 +	get_implementation(), bits, stride, bpp, x, y, width, height, filler);
   1.771 +}
   1.772 +
   1.773 +static uint32_t
   1.774 +color_to_uint32 (const pixman_color_t *color)
   1.775 +{
   1.776 +    return
   1.777 +        (color->alpha >> 8 << 24) |
   1.778 +        (color->red >> 8 << 16) |
   1.779 +        (color->green & 0xff00) |
   1.780 +        (color->blue >> 8);
   1.781 +}
   1.782 +
   1.783 +static pixman_bool_t
   1.784 +color_to_pixel (const pixman_color_t *color,
   1.785 +                uint32_t *            pixel,
   1.786 +                pixman_format_code_t  format)
   1.787 +{
   1.788 +    uint32_t c = color_to_uint32 (color);
   1.789 +
   1.790 +    if (!(format == PIXMAN_a8r8g8b8     ||
   1.791 +          format == PIXMAN_x8r8g8b8     ||
   1.792 +          format == PIXMAN_a8b8g8r8     ||
   1.793 +          format == PIXMAN_x8b8g8r8     ||
   1.794 +          format == PIXMAN_b8g8r8a8     ||
   1.795 +          format == PIXMAN_b8g8r8x8     ||
   1.796 +          format == PIXMAN_r8g8b8a8     ||
   1.797 +          format == PIXMAN_r8g8b8x8     ||
   1.798 +          format == PIXMAN_r5g6b5       ||
   1.799 +          format == PIXMAN_b5g6r5       ||
   1.800 +          format == PIXMAN_a8           ||
   1.801 +          format == PIXMAN_a1))
   1.802 +    {
   1.803 +	return FALSE;
   1.804 +    }
   1.805 +
   1.806 +    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
   1.807 +    {
   1.808 +	c = ((c & 0xff000000) >>  0) |
   1.809 +	    ((c & 0x00ff0000) >> 16) |
   1.810 +	    ((c & 0x0000ff00) >>  0) |
   1.811 +	    ((c & 0x000000ff) << 16);
   1.812 +    }
   1.813 +    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
   1.814 +    {
   1.815 +	c = ((c & 0xff000000) >> 24) |
   1.816 +	    ((c & 0x00ff0000) >>  8) |
   1.817 +	    ((c & 0x0000ff00) <<  8) |
   1.818 +	    ((c & 0x000000ff) << 24);
   1.819 +    }
   1.820 +    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA)
   1.821 +	c = ((c & 0xff000000) >> 24) | (c << 8);
   1.822 +
   1.823 +    if (format == PIXMAN_a1)
   1.824 +	c = c >> 31;
   1.825 +    else if (format == PIXMAN_a8)
   1.826 +	c = c >> 24;
   1.827 +    else if (format == PIXMAN_r5g6b5 ||
   1.828 +             format == PIXMAN_b5g6r5)
   1.829 +	c = convert_8888_to_0565 (c);
   1.830 +
   1.831 +#if 0
   1.832 +    printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
   1.833 +    printf ("pixel: %x\n", c);
   1.834 +#endif
   1.835 +
   1.836 +    *pixel = c;
   1.837 +    return TRUE;
   1.838 +}
   1.839 +
   1.840 +PIXMAN_EXPORT pixman_bool_t
   1.841 +pixman_image_fill_rectangles (pixman_op_t                 op,
   1.842 +                              pixman_image_t *            dest,
   1.843 +			      const pixman_color_t *      color,
   1.844 +                              int                         n_rects,
   1.845 +                              const pixman_rectangle16_t *rects)
   1.846 +{
   1.847 +    pixman_box32_t stack_boxes[6];
   1.848 +    pixman_box32_t *boxes;
   1.849 +    pixman_bool_t result;
   1.850 +    int i;
   1.851 +
   1.852 +    if (n_rects > 6)
   1.853 +    {
   1.854 +        boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
   1.855 +        if (boxes == NULL)
   1.856 +            return FALSE;
   1.857 +    }
   1.858 +    else
   1.859 +    {
   1.860 +        boxes = stack_boxes;
   1.861 +    }
   1.862 +
   1.863 +    for (i = 0; i < n_rects; ++i)
   1.864 +    {
   1.865 +        boxes[i].x1 = rects[i].x;
   1.866 +        boxes[i].y1 = rects[i].y;
   1.867 +        boxes[i].x2 = boxes[i].x1 + rects[i].width;
   1.868 +        boxes[i].y2 = boxes[i].y1 + rects[i].height;
   1.869 +    }
   1.870 +
   1.871 +    result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
   1.872 +
   1.873 +    if (boxes != stack_boxes)
   1.874 +        free (boxes);
   1.875 +    
   1.876 +    return result;
   1.877 +}
   1.878 +
   1.879 +PIXMAN_EXPORT pixman_bool_t
   1.880 +pixman_image_fill_boxes (pixman_op_t           op,
   1.881 +                         pixman_image_t *      dest,
   1.882 +                         const pixman_color_t *color,
   1.883 +                         int                   n_boxes,
   1.884 +                         const pixman_box32_t *boxes)
   1.885 +{
   1.886 +    pixman_image_t *solid;
   1.887 +    pixman_color_t c;
   1.888 +    int i;
   1.889 +
   1.890 +    _pixman_image_validate (dest);
   1.891 +    
   1.892 +    if (color->alpha == 0xffff)
   1.893 +    {
   1.894 +        if (op == PIXMAN_OP_OVER)
   1.895 +            op = PIXMAN_OP_SRC;
   1.896 +    }
   1.897 +
   1.898 +    if (op == PIXMAN_OP_CLEAR)
   1.899 +    {
   1.900 +        c.red = 0;
   1.901 +        c.green = 0;
   1.902 +        c.blue = 0;
   1.903 +        c.alpha = 0;
   1.904 +
   1.905 +        color = &c;
   1.906 +
   1.907 +        op = PIXMAN_OP_SRC;
   1.908 +    }
   1.909 +
   1.910 +    if (op == PIXMAN_OP_SRC)
   1.911 +    {
   1.912 +        uint32_t pixel;
   1.913 +
   1.914 +        if (color_to_pixel (color, &pixel, dest->bits.format))
   1.915 +        {
   1.916 +            pixman_region32_t fill_region;
   1.917 +            int n_rects, j;
   1.918 +            pixman_box32_t *rects;
   1.919 +
   1.920 +            if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
   1.921 +                return FALSE;
   1.922 +
   1.923 +            if (dest->common.have_clip_region)
   1.924 +            {
   1.925 +                if (!pixman_region32_intersect (&fill_region,
   1.926 +                                                &fill_region,
   1.927 +                                                &dest->common.clip_region))
   1.928 +                    return FALSE;
   1.929 +            }
   1.930 +
   1.931 +            rects = pixman_region32_rectangles (&fill_region, &n_rects);
   1.932 +            for (j = 0; j < n_rects; ++j)
   1.933 +            {
   1.934 +                const pixman_box32_t *rect = &(rects[j]);
   1.935 +                pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
   1.936 +                             rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
   1.937 +                             pixel);
   1.938 +            }
   1.939 +
   1.940 +            pixman_region32_fini (&fill_region);
   1.941 +            return TRUE;
   1.942 +        }
   1.943 +    }
   1.944 +
   1.945 +    solid = pixman_image_create_solid_fill (color);
   1.946 +    if (!solid)
   1.947 +        return FALSE;
   1.948 +
   1.949 +    for (i = 0; i < n_boxes; ++i)
   1.950 +    {
   1.951 +        const pixman_box32_t *box = &(boxes[i]);
   1.952 +
   1.953 +        pixman_image_composite32 (op, solid, NULL, dest,
   1.954 +                                  0, 0, 0, 0,
   1.955 +                                  box->x1, box->y1,
   1.956 +                                  box->x2 - box->x1, box->y2 - box->y1);
   1.957 +    }
   1.958 +
   1.959 +    pixman_image_unref (solid);
   1.960 +
   1.961 +    return TRUE;
   1.962 +}
   1.963 +
   1.964 +/**
   1.965 + * pixman_version:
   1.966 + *
   1.967 + * Returns the version of the pixman library encoded in a single
   1.968 + * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
   1.969 + * later versions compare greater than earlier versions.
   1.970 + *
   1.971 + * A run-time comparison to check that pixman's version is greater than
   1.972 + * or equal to version X.Y.Z could be performed as follows:
   1.973 + *
   1.974 + * <informalexample><programlisting>
   1.975 + * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
   1.976 + * </programlisting></informalexample>
   1.977 + *
   1.978 + * See also pixman_version_string() as well as the compile-time
   1.979 + * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
   1.980 + *
   1.981 + * Return value: the encoded version.
   1.982 + **/
   1.983 +PIXMAN_EXPORT int
   1.984 +pixman_version (void)
   1.985 +{
   1.986 +    return PIXMAN_VERSION;
   1.987 +}
   1.988 +
   1.989 +/**
   1.990 + * pixman_version_string:
   1.991 + *
   1.992 + * Returns the version of the pixman library as a human-readable string
   1.993 + * of the form "X.Y.Z".
   1.994 + *
   1.995 + * See also pixman_version() as well as the compile-time equivalents
   1.996 + * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
   1.997 + *
   1.998 + * Return value: a string containing the version.
   1.999 + **/
  1.1000 +PIXMAN_EXPORT const char*
  1.1001 +pixman_version_string (void)
  1.1002 +{
  1.1003 +    return PIXMAN_VERSION_STRING;
  1.1004 +}
  1.1005 +
  1.1006 +/**
  1.1007 + * pixman_format_supported_source:
  1.1008 + * @format: A pixman_format_code_t format
  1.1009 + *
  1.1010 + * Return value: whether the provided format code is a supported
  1.1011 + * format for a pixman surface used as a source in
  1.1012 + * rendering.
  1.1013 + *
  1.1014 + * Currently, all pixman_format_code_t values are supported.
  1.1015 + **/
  1.1016 +PIXMAN_EXPORT pixman_bool_t
  1.1017 +pixman_format_supported_source (pixman_format_code_t format)
  1.1018 +{
  1.1019 +    switch (format)
  1.1020 +    {
  1.1021 +    /* 32 bpp formats */
  1.1022 +    case PIXMAN_a2b10g10r10:
  1.1023 +    case PIXMAN_x2b10g10r10:
  1.1024 +    case PIXMAN_a2r10g10b10:
  1.1025 +    case PIXMAN_x2r10g10b10:
  1.1026 +    case PIXMAN_a8r8g8b8:
  1.1027 +    case PIXMAN_a8r8g8b8_sRGB:
  1.1028 +    case PIXMAN_x8r8g8b8:
  1.1029 +    case PIXMAN_a8b8g8r8:
  1.1030 +    case PIXMAN_x8b8g8r8:
  1.1031 +    case PIXMAN_b8g8r8a8:
  1.1032 +    case PIXMAN_b8g8r8x8:
  1.1033 +    case PIXMAN_r8g8b8a8:
  1.1034 +    case PIXMAN_r8g8b8x8:
  1.1035 +    case PIXMAN_r8g8b8:
  1.1036 +    case PIXMAN_b8g8r8:
  1.1037 +    case PIXMAN_r5g6b5:
  1.1038 +    case PIXMAN_b5g6r5:
  1.1039 +    case PIXMAN_x14r6g6b6:
  1.1040 +    /* 16 bpp formats */
  1.1041 +    case PIXMAN_a1r5g5b5:
  1.1042 +    case PIXMAN_x1r5g5b5:
  1.1043 +    case PIXMAN_a1b5g5r5:
  1.1044 +    case PIXMAN_x1b5g5r5:
  1.1045 +    case PIXMAN_a4r4g4b4:
  1.1046 +    case PIXMAN_x4r4g4b4:
  1.1047 +    case PIXMAN_a4b4g4r4:
  1.1048 +    case PIXMAN_x4b4g4r4:
  1.1049 +    /* 8bpp formats */
  1.1050 +    case PIXMAN_a8:
  1.1051 +    case PIXMAN_r3g3b2:
  1.1052 +    case PIXMAN_b2g3r3:
  1.1053 +    case PIXMAN_a2r2g2b2:
  1.1054 +    case PIXMAN_a2b2g2r2:
  1.1055 +    case PIXMAN_c8:
  1.1056 +    case PIXMAN_g8:
  1.1057 +    case PIXMAN_x4a4:
  1.1058 +    /* Collides with PIXMAN_c8
  1.1059 +       case PIXMAN_x4c4:
  1.1060 +     */
  1.1061 +    /* Collides with PIXMAN_g8
  1.1062 +       case PIXMAN_x4g4:
  1.1063 +     */
  1.1064 +    /* 4bpp formats */
  1.1065 +    case PIXMAN_a4:
  1.1066 +    case PIXMAN_r1g2b1:
  1.1067 +    case PIXMAN_b1g2r1:
  1.1068 +    case PIXMAN_a1r1g1b1:
  1.1069 +    case PIXMAN_a1b1g1r1:
  1.1070 +    case PIXMAN_c4:
  1.1071 +    case PIXMAN_g4:
  1.1072 +    /* 1bpp formats */
  1.1073 +    case PIXMAN_a1:
  1.1074 +    case PIXMAN_g1:
  1.1075 +    /* YUV formats */
  1.1076 +    case PIXMAN_yuy2:
  1.1077 +    case PIXMAN_yv12:
  1.1078 +	return TRUE;
  1.1079 +
  1.1080 +    default:
  1.1081 +	return FALSE;
  1.1082 +    }
  1.1083 +}
  1.1084 +
  1.1085 +/**
  1.1086 + * pixman_format_supported_destination:
  1.1087 + * @format: A pixman_format_code_t format
  1.1088 + *
  1.1089 + * Return value: whether the provided format code is a supported
  1.1090 + * format for a pixman surface used as a destination in
  1.1091 + * rendering.
  1.1092 + *
  1.1093 + * Currently, all pixman_format_code_t values are supported
  1.1094 + * except for the YUV formats.
  1.1095 + **/
  1.1096 +PIXMAN_EXPORT pixman_bool_t
  1.1097 +pixman_format_supported_destination (pixman_format_code_t format)
  1.1098 +{
  1.1099 +    /* YUV formats cannot be written to at the moment */
  1.1100 +    if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
  1.1101 +	return FALSE;
  1.1102 +
  1.1103 +    return pixman_format_supported_source (format);
  1.1104 +}
  1.1105 +
  1.1106 +PIXMAN_EXPORT pixman_bool_t
  1.1107 +pixman_compute_composite_region (pixman_region16_t * region,
  1.1108 +                                 pixman_image_t *    src_image,
  1.1109 +                                 pixman_image_t *    mask_image,
  1.1110 +                                 pixman_image_t *    dest_image,
  1.1111 +                                 int16_t             src_x,
  1.1112 +                                 int16_t             src_y,
  1.1113 +                                 int16_t             mask_x,
  1.1114 +                                 int16_t             mask_y,
  1.1115 +                                 int16_t             dest_x,
  1.1116 +                                 int16_t             dest_y,
  1.1117 +                                 uint16_t            width,
  1.1118 +                                 uint16_t            height)
  1.1119 +{
  1.1120 +    pixman_region32_t r32;
  1.1121 +    pixman_bool_t retval;
  1.1122 +
  1.1123 +    pixman_region32_init (&r32);
  1.1124 +
  1.1125 +    retval = _pixman_compute_composite_region32 (
  1.1126 +	&r32, src_image, mask_image, dest_image,
  1.1127 +	src_x, src_y, mask_x, mask_y, dest_x, dest_y,
  1.1128 +	width, height);
  1.1129 +
  1.1130 +    if (retval)
  1.1131 +    {
  1.1132 +	if (!pixman_region16_copy_from_region32 (region, &r32))
  1.1133 +	    retval = FALSE;
  1.1134 +    }
  1.1135 +
  1.1136 +    pixman_region32_fini (&r32);
  1.1137 +    return retval;
  1.1138 +}

mercurial