gfx/cairo/libpixman/src/pixman.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial