LCOV - code coverage report
Current view: directory - gfx/cairo/libpixman/src - pixman.c (source / functions) Found Hit Coverage
Test: app.info Lines: 444 186 41.9 %
Date: 2012-06-02 Functions: 20 7 35.0 %

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

Generated by: LCOV version 1.7