LCOV - code coverage report
Current view: directory - gfx/cairo/libpixman/src - pixman-bits-image.c (source / functions) Found Hit Coverage
Test: app.info Lines: 567 33 5.8 %
Date: 2012-06-02 Functions: 60 2 3.3 %

       1                 : /*
       2                 :  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
       3                 :  *             2005 Lars Knoll & Zack Rusin, Trolltech
       4                 :  *             2008 Aaron Plattner, NVIDIA Corporation
       5                 :  * Copyright © 2000 SuSE, Inc.
       6                 :  * Copyright © 2007, 2009 Red Hat, Inc.
       7                 :  * Copyright © 2008 André Tupinambá <andrelrt@gmail.com>
       8                 :  *
       9                 :  * Permission to use, copy, modify, distribute, and sell this software and its
      10                 :  * documentation for any purpose is hereby granted without fee, provided that
      11                 :  * the above copyright notice appear in all copies and that both that
      12                 :  * copyright notice and this permission notice appear in supporting
      13                 :  * documentation, and that the name of Keith Packard not be used in
      14                 :  * advertising or publicity pertaining to distribution of the software without
      15                 :  * specific, written prior permission.  Keith Packard makes no
      16                 :  * representations about the suitability of this software for any purpose.  It
      17                 :  * is provided "as is" without express or implied warranty.
      18                 :  *
      19                 :  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
      20                 :  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
      21                 :  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
      22                 :  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      23                 :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
      24                 :  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
      25                 :  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
      26                 :  * SOFTWARE.
      27                 :  */
      28                 : 
      29                 : #ifdef HAVE_CONFIG_H
      30                 : #include <config.h>
      31                 : #endif
      32                 : #include <stdio.h>
      33                 : #include <stdlib.h>
      34                 : #include <string.h>
      35                 : #include "pixman-private.h"
      36                 : #include "pixman-combine32.h"
      37                 : 
      38                 : /*
      39                 :  * By default, just evaluate the image at 32bpp and expand.  Individual image
      40                 :  * types can plug in a better scanline getter if they want to. For example
      41                 :  * we  could produce smoother gradients by evaluating them at higher color
      42                 :  * depth, but that's a project for the future.
      43                 :  */
      44                 : static void
      45               0 : _pixman_image_get_scanline_generic_64 (pixman_image_t * image,
      46                 :                                        int              x,
      47                 :                                        int              y,
      48                 :                                        int              width,
      49                 :                                        uint32_t *       buffer,
      50                 :                                        const uint32_t * mask)
      51                 : {
      52               0 :     uint32_t *mask8 = NULL;
      53                 : 
      54                 :     /* Contract the mask image, if one exists, so that the 32-bit fetch
      55                 :      * function can use it.
      56                 :      */
      57               0 :     if (mask)
      58                 :     {
      59               0 :         mask8 = pixman_malloc_ab (width, sizeof(uint32_t));
      60               0 :         if (!mask8)
      61               0 :             return;
      62                 : 
      63               0 :         pixman_contract (mask8, (uint64_t *)mask, width);
      64                 :     }
      65                 : 
      66                 :     /* Fetch the source image into the first half of buffer. */
      67               0 :     image->bits.get_scanline_32 (image, x, y, width, (uint32_t*)buffer, mask8);
      68                 : 
      69                 :     /* Expand from 32bpp to 64bpp in place. */
      70               0 :     pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, width);
      71                 : 
      72               0 :     free (mask8);
      73                 : }
      74                 : 
      75                 : /* Fetch functions */
      76                 : 
      77                 : static force_inline uint32_t
      78               0 : fetch_pixel_no_alpha (bits_image_t *image,
      79                 :                       int x, int y, pixman_bool_t check_bounds)
      80                 : {
      81               0 :     if (check_bounds &&
      82               0 :         (x < 0 || x >= image->width || y < 0 || y >= image->height))
      83                 :     {
      84               0 :         return 0;
      85                 :     }
      86                 : 
      87               0 :     return image->fetch_pixel_32 (image, x, y);
      88                 : }
      89                 : 
      90                 : typedef uint32_t (* get_pixel_t) (bits_image_t *image,
      91                 :                                   int x, int y, pixman_bool_t check_bounds);
      92                 : 
      93                 : static force_inline void
      94                 : repeat (pixman_repeat_t repeat, int size, int *coord)
      95                 : {
      96               0 :     switch (repeat)
      97                 :     {
      98                 :     case PIXMAN_REPEAT_NORMAL:
      99               0 :         *coord = MOD (*coord, size);
     100                 :         break;
     101                 : 
     102                 :     case PIXMAN_REPEAT_PAD:
     103               0 :         *coord = CLIP (*coord, 0, size - 1);
     104                 :         break;
     105                 : 
     106                 :     case PIXMAN_REPEAT_REFLECT:
     107               0 :         *coord = MOD (*coord, size * 2);
     108                 : 
     109               0 :         if (*coord >= size)
     110               0 :             *coord = size * 2 - *coord - 1;
     111                 :         break;
     112                 : 
     113                 :     case PIXMAN_REPEAT_NONE:
     114                 :         break;
     115                 : 
     116                 :     default:
     117                 :         break;
     118                 :     }
     119                 : }
     120                 : 
     121                 : static force_inline uint32_t
     122                 : bits_image_fetch_pixel_nearest (bits_image_t   *image,
     123                 :                                 pixman_fixed_t  x,
     124                 :                                 pixman_fixed_t  y,
     125                 :                                 get_pixel_t     get_pixel)
     126                 : {
     127               0 :     int x0 = pixman_fixed_to_int (x - pixman_fixed_e);
     128               0 :     int y0 = pixman_fixed_to_int (y - pixman_fixed_e);
     129                 : 
     130               0 :     if (image->common.repeat != PIXMAN_REPEAT_NONE)
     131                 :     {
     132               0 :         repeat (image->common.repeat, image->width, &x0);
     133               0 :         repeat (image->common.repeat, image->height, &y0);
     134                 : 
     135               0 :         return get_pixel (image, x0, y0, FALSE);
     136                 :     }
     137                 :     else
     138                 :     {
     139               0 :         return get_pixel (image, x0, y0, TRUE);
     140                 :     }
     141                 : }
     142                 : 
     143                 : #if SIZEOF_LONG > 4
     144                 : 
     145                 : static force_inline uint32_t
     146                 : bilinear_interpolation (uint32_t tl, uint32_t tr,
     147                 :                         uint32_t bl, uint32_t br,
     148                 :                         int distx, int disty)
     149                 : {
     150                 :     uint64_t distxy, distxiy, distixy, distixiy;
     151                 :     uint64_t tl64, tr64, bl64, br64;
     152                 :     uint64_t f, r;
     153                 : 
     154                 :     distxy = distx * disty;
     155                 :     distxiy = distx * (256 - disty);
     156                 :     distixy = (256 - distx) * disty;
     157                 :     distixiy = (256 - distx) * (256 - disty);
     158                 : 
     159                 :     /* Alpha and Blue */
     160                 :     tl64 = tl & 0xff0000ff;
     161                 :     tr64 = tr & 0xff0000ff;
     162                 :     bl64 = bl & 0xff0000ff;
     163                 :     br64 = br & 0xff0000ff;
     164                 : 
     165                 :     f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
     166                 :     r = f & 0x0000ff0000ff0000ull;
     167                 : 
     168                 :     /* Red and Green */
     169                 :     tl64 = tl;
     170                 :     tl64 = ((tl64 << 16) & 0x000000ff00000000ull) | (tl64 & 0x0000ff00ull);
     171                 : 
     172                 :     tr64 = tr;
     173                 :     tr64 = ((tr64 << 16) & 0x000000ff00000000ull) | (tr64 & 0x0000ff00ull);
     174                 : 
     175                 :     bl64 = bl;
     176                 :     bl64 = ((bl64 << 16) & 0x000000ff00000000ull) | (bl64 & 0x0000ff00ull);
     177                 : 
     178                 :     br64 = br;
     179                 :     br64 = ((br64 << 16) & 0x000000ff00000000ull) | (br64 & 0x0000ff00ull);
     180                 : 
     181                 :     f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
     182                 :     r |= ((f >> 16) & 0x000000ff00000000ull) | (f & 0xff000000ull);
     183                 : 
     184                 :     return (uint32_t)(r >> 16);
     185                 : }
     186                 : 
     187                 : #else
     188                 : 
     189                 : static force_inline uint32_t
     190                 : bilinear_interpolation (uint32_t tl, uint32_t tr,
     191                 :                         uint32_t bl, uint32_t br,
     192                 :                         int distx, int disty)
     193                 : {
     194                 :     int distxy, distxiy, distixy, distixiy;
     195                 :     uint32_t f, r;
     196                 : 
     197               0 :     distxy = distx * disty;
     198               0 :     distxiy = (distx << 8) - distxy;      /* distx * (256 - disty) */
     199               0 :     distixy = (disty << 8) - distxy;      /* disty * (256 - distx) */
     200               0 :     distixiy =
     201               0 :         256 * 256 - (disty << 8) -
     202               0 :         (distx << 8) + distxy;            /* (256 - distx) * (256 - disty) */
     203                 : 
     204                 :     /* Blue */
     205               0 :     r = (tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy
     206               0 :       + (bl & 0x000000ff) * distixy  + (br & 0x000000ff) * distxy;
     207                 : 
     208                 :     /* Green */
     209               0 :     f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy
     210               0 :       + (bl & 0x0000ff00) * distixy  + (br & 0x0000ff00) * distxy;
     211               0 :     r |= f & 0xff000000;
     212                 : 
     213               0 :     tl >>= 16;
     214               0 :     tr >>= 16;
     215               0 :     bl >>= 16;
     216               0 :     br >>= 16;
     217               0 :     r >>= 16;
     218                 : 
     219                 :     /* Red */
     220               0 :     f = (tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy
     221               0 :       + (bl & 0x000000ff) * distixy  + (br & 0x000000ff) * distxy;
     222               0 :     r |= f & 0x00ff0000;
     223                 : 
     224                 :     /* Alpha */
     225               0 :     f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy
     226               0 :       + (bl & 0x0000ff00) * distixy  + (br & 0x0000ff00) * distxy;
     227               0 :     r |= f & 0xff000000;
     228                 : 
     229               0 :     return r;
     230                 : }
     231                 : 
     232                 : #endif
     233                 : 
     234                 : static force_inline uint32_t
     235                 : bits_image_fetch_pixel_bilinear (bits_image_t   *image,
     236                 :                                  pixman_fixed_t  x,
     237                 :                                  pixman_fixed_t  y,
     238                 :                                  get_pixel_t     get_pixel)
     239                 : {
     240               0 :     pixman_repeat_t repeat_mode = image->common.repeat;
     241               0 :     int width = image->width;
     242               0 :     int height = image->height;
     243                 :     int x1, y1, x2, y2;
     244                 :     uint32_t tl, tr, bl, br;
     245                 :     int32_t distx, disty;
     246                 : 
     247               0 :     x1 = x - pixman_fixed_1 / 2;
     248               0 :     y1 = y - pixman_fixed_1 / 2;
     249                 : 
     250               0 :     distx = (x1 >> 8) & 0xff;
     251               0 :     disty = (y1 >> 8) & 0xff;
     252                 : 
     253               0 :     x1 = pixman_fixed_to_int (x1);
     254               0 :     y1 = pixman_fixed_to_int (y1);
     255               0 :     x2 = x1 + 1;
     256               0 :     y2 = y1 + 1;
     257                 : 
     258               0 :     if (repeat_mode != PIXMAN_REPEAT_NONE)
     259                 :     {
     260                 :         repeat (repeat_mode, width, &x1);
     261                 :         repeat (repeat_mode, height, &y1);
     262                 :         repeat (repeat_mode, width, &x2);
     263                 :         repeat (repeat_mode, height, &y2);
     264                 : 
     265               0 :         tl = get_pixel (image, x1, y1, FALSE);
     266               0 :         bl = get_pixel (image, x1, y2, FALSE);
     267               0 :         tr = get_pixel (image, x2, y1, FALSE);
     268               0 :         br = get_pixel (image, x2, y2, FALSE);
     269                 :     }
     270                 :     else
     271                 :     {
     272               0 :         tl = get_pixel (image, x1, y1, TRUE);
     273               0 :         tr = get_pixel (image, x2, y1, TRUE);
     274               0 :         bl = get_pixel (image, x1, y2, TRUE);
     275               0 :         br = get_pixel (image, x2, y2, TRUE);
     276                 :     }
     277                 : 
     278                 :     return bilinear_interpolation (tl, tr, bl, br, distx, disty);
     279                 : }
     280                 : 
     281                 : static void
     282               0 : bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima,
     283                 :                                           int              offset,
     284                 :                                           int              line,
     285                 :                                           int              width,
     286                 :                                           uint32_t *       buffer,
     287                 :                                           const uint32_t * mask)
     288                 : {
     289               0 :     bits_image_t *bits = &ima->bits;
     290                 :     pixman_fixed_t x_top, x_bottom, x;
     291                 :     pixman_fixed_t ux_top, ux_bottom, ux;
     292                 :     pixman_vector_t v;
     293                 :     uint32_t top_mask, bottom_mask;
     294                 :     uint32_t *top_row;
     295                 :     uint32_t *bottom_row;
     296                 :     uint32_t *end;
     297               0 :     uint32_t zero[2] = { 0, 0 };
     298               0 :     uint32_t one = 1;
     299                 :     int y, y1, y2;
     300                 :     int disty;
     301                 :     int mask_inc;
     302                 :     int w;
     303                 : 
     304                 :     /* reference point is the center of the pixel */
     305               0 :     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
     306               0 :     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
     307               0 :     v.vector[2] = pixman_fixed_1;
     308                 : 
     309               0 :     if (!pixman_transform_point_3d (bits->common.transform, &v))
     310               0 :         return;
     311                 : 
     312               0 :     ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
     313               0 :     x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
     314                 : 
     315               0 :     y = v.vector[1] - pixman_fixed_1/2;
     316               0 :     disty = (y >> 8) & 0xff;
     317                 : 
     318                 :     /* Load the pointers to the first and second lines from the source
     319                 :      * image that bilinear code must read.
     320                 :      *
     321                 :      * The main trick in this code is about the check if any line are
     322                 :      * outside of the image;
     323                 :      *
     324                 :      * When I realize that a line (any one) is outside, I change
     325                 :      * the pointer to a dummy area with zeros. Once I change this, I
     326                 :      * must be sure the pointer will not change, so I set the
     327                 :      * variables to each pointer increments inside the loop.
     328                 :      */
     329               0 :     y1 = pixman_fixed_to_int (y);
     330               0 :     y2 = y1 + 1;
     331                 : 
     332               0 :     if (y1 < 0 || y1 >= bits->height)
     333                 :     {
     334               0 :         top_row = zero;
     335               0 :         x_top = 0;
     336               0 :         ux_top = 0;
     337                 :     }
     338                 :     else
     339                 :     {
     340               0 :         top_row = bits->bits + y1 * bits->rowstride;
     341               0 :         x_top = x;
     342               0 :         ux_top = ux;
     343                 :     }
     344                 : 
     345               0 :     if (y2 < 0 || y2 >= bits->height)
     346                 :     {
     347               0 :         bottom_row = zero;
     348               0 :         x_bottom = 0;
     349               0 :         ux_bottom = 0;
     350                 :     }
     351                 :     else
     352                 :     {
     353               0 :         bottom_row = bits->bits + y2 * bits->rowstride;
     354               0 :         x_bottom = x;
     355               0 :         ux_bottom = ux;
     356                 :     }
     357                 : 
     358                 :     /* Instead of checking whether the operation uses the mast in
     359                 :      * each loop iteration, verify this only once and prepare the
     360                 :      * variables to make the code smaller inside the loop.
     361                 :      */
     362               0 :     if (!mask)
     363                 :     {
     364               0 :         mask_inc = 0;
     365               0 :         mask = &one;
     366                 :     }
     367                 :     else
     368                 :     {
     369                 :         /* If have a mask, prepare the variables to check it */
     370               0 :         mask_inc = 1;
     371                 :     }
     372                 : 
     373                 :     /* If both are zero, then the whole thing is zero */
     374               0 :     if (top_row == zero && bottom_row == zero)
     375                 :     {
     376               0 :         memset (buffer, 0, width * sizeof (uint32_t));
     377               0 :         return;
     378                 :     }
     379               0 :     else if (bits->format == PIXMAN_x8r8g8b8)
     380                 :     {
     381               0 :         if (top_row == zero)
     382                 :         {
     383               0 :             top_mask = 0;
     384               0 :             bottom_mask = 0xff000000;
     385                 :         }
     386               0 :         else if (bottom_row == zero)
     387                 :         {
     388               0 :             top_mask = 0xff000000;
     389               0 :             bottom_mask = 0;
     390                 :         }
     391                 :         else
     392                 :         {
     393               0 :             top_mask = 0xff000000;
     394               0 :             bottom_mask = 0xff000000;
     395                 :         }
     396                 :     }
     397                 :     else
     398                 :     {
     399               0 :         top_mask = 0;
     400               0 :         bottom_mask = 0;
     401                 :     }
     402                 : 
     403               0 :     end = buffer + width;
     404                 : 
     405                 :     /* Zero fill to the left of the image */
     406               0 :     while (buffer < end && x < pixman_fixed_minus_1)
     407                 :     {
     408               0 :         *buffer++ = 0;
     409               0 :         x += ux;
     410               0 :         x_top += ux_top;
     411               0 :         x_bottom += ux_bottom;
     412               0 :         mask += mask_inc;
     413                 :     }
     414                 : 
     415                 :     /* Left edge
     416                 :      */
     417               0 :     while (buffer < end && x < 0)
     418                 :     {
     419                 :         uint32_t tr, br;
     420                 :         int32_t distx;
     421                 : 
     422               0 :         tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
     423               0 :         br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
     424                 : 
     425               0 :         distx = (x >> 8) & 0xff;
     426                 : 
     427               0 :         *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
     428                 : 
     429               0 :         x += ux;
     430               0 :         x_top += ux_top;
     431               0 :         x_bottom += ux_bottom;
     432               0 :         mask += mask_inc;
     433                 :     }
     434                 : 
     435                 :     /* Main part */
     436               0 :     w = pixman_int_to_fixed (bits->width - 1);
     437                 : 
     438               0 :     while (buffer < end  &&  x < w)
     439                 :     {
     440               0 :         if (*mask)
     441                 :         {
     442                 :             uint32_t tl, tr, bl, br;
     443                 :             int32_t distx;
     444                 : 
     445               0 :             tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
     446               0 :             tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask;
     447               0 :             bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
     448               0 :             br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
     449                 : 
     450               0 :             distx = (x >> 8) & 0xff;
     451                 : 
     452               0 :             *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
     453                 :         }
     454                 : 
     455               0 :         buffer++;
     456               0 :         x += ux;
     457               0 :         x_top += ux_top;
     458               0 :         x_bottom += ux_bottom;
     459               0 :         mask += mask_inc;
     460                 :     }
     461                 : 
     462                 :     /* Right Edge */
     463               0 :     w = pixman_int_to_fixed (bits->width);
     464               0 :     while (buffer < end  &&  x < w)
     465                 :     {
     466               0 :         if (*mask)
     467                 :         {
     468                 :             uint32_t tl, bl;
     469                 :             int32_t distx;
     470                 : 
     471               0 :             tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
     472               0 :             bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
     473                 : 
     474               0 :             distx = (x >> 8) & 0xff;
     475                 : 
     476               0 :             *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
     477                 :         }
     478                 : 
     479               0 :         buffer++;
     480               0 :         x += ux;
     481               0 :         x_top += ux_top;
     482               0 :         x_bottom += ux_bottom;
     483               0 :         mask += mask_inc;
     484                 :     }
     485                 : 
     486                 :     /* Zero fill to the left of the image */
     487               0 :     while (buffer < end)
     488               0 :         *buffer++ = 0;
     489                 : }
     490                 : 
     491                 : static force_inline uint32_t
     492                 : bits_image_fetch_pixel_convolution (bits_image_t   *image,
     493                 :                                     pixman_fixed_t  x,
     494                 :                                     pixman_fixed_t  y,
     495                 :                                     get_pixel_t     get_pixel)
     496                 : {
     497               0 :     pixman_fixed_t *params = image->common.filter_params;
     498               0 :     int x_off = (params[0] - pixman_fixed_1) >> 1;
     499               0 :     int y_off = (params[1] - pixman_fixed_1) >> 1;
     500               0 :     int32_t cwidth = pixman_fixed_to_int (params[0]);
     501               0 :     int32_t cheight = pixman_fixed_to_int (params[1]);
     502                 :     int32_t srtot, sgtot, sbtot, satot;
     503                 :     int32_t i, j, x1, x2, y1, y2;
     504               0 :     pixman_repeat_t repeat_mode = image->common.repeat;
     505               0 :     int width = image->width;
     506               0 :     int height = image->height;
     507                 : 
     508               0 :     params += 2;
     509                 : 
     510               0 :     x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
     511               0 :     y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
     512               0 :     x2 = x1 + cwidth;
     513               0 :     y2 = y1 + cheight;
     514                 : 
     515               0 :     srtot = sgtot = sbtot = satot = 0;
     516                 : 
     517               0 :     for (i = y1; i < y2; ++i)
     518                 :     {
     519               0 :         for (j = x1; j < x2; ++j)
     520                 :         {
     521               0 :             int rx = j;
     522               0 :             int ry = i;
     523                 : 
     524               0 :             pixman_fixed_t f = *params;
     525                 : 
     526               0 :             if (f)
     527                 :             {
     528                 :                 uint32_t pixel;
     529                 : 
     530               0 :                 if (repeat_mode != PIXMAN_REPEAT_NONE)
     531                 :                 {
     532                 :                     repeat (repeat_mode, width, &rx);
     533                 :                     repeat (repeat_mode, height, &ry);
     534                 : 
     535               0 :                     pixel = get_pixel (image, rx, ry, FALSE);
     536                 :                 }
     537                 :                 else
     538                 :                 {
     539               0 :                     pixel = get_pixel (image, rx, ry, TRUE);
     540                 :                 }
     541                 : 
     542               0 :                 srtot += RED_8 (pixel) * f;
     543               0 :                 sgtot += GREEN_8 (pixel) * f;
     544               0 :                 sbtot += BLUE_8 (pixel) * f;
     545               0 :                 satot += ALPHA_8 (pixel) * f;
     546                 :             }
     547                 : 
     548               0 :             params++;
     549                 :         }
     550                 :     }
     551                 : 
     552               0 :     satot >>= 16;
     553               0 :     srtot >>= 16;
     554               0 :     sgtot >>= 16;
     555               0 :     sbtot >>= 16;
     556                 : 
     557               0 :     satot = CLIP (satot, 0, 0xff);
     558               0 :     srtot = CLIP (srtot, 0, 0xff);
     559               0 :     sgtot = CLIP (sgtot, 0, 0xff);
     560               0 :     sbtot = CLIP (sbtot, 0, 0xff);
     561                 : 
     562               0 :     return ((satot << 24) | (srtot << 16) | (sgtot <<  8) | (sbtot));
     563                 : }
     564                 : 
     565                 : static force_inline uint32_t
     566                 : bits_image_fetch_pixel_filtered (bits_image_t *image,
     567                 :                                  pixman_fixed_t x,
     568                 :                                  pixman_fixed_t y,
     569                 :                                  get_pixel_t    get_pixel)
     570                 : {
     571               0 :     switch (image->common.filter)
     572                 :     {
     573                 :     case PIXMAN_FILTER_NEAREST:
     574                 :     case PIXMAN_FILTER_FAST:
     575                 :         return bits_image_fetch_pixel_nearest (image, x, y, get_pixel);
     576                 :         break;
     577                 : 
     578                 :     case PIXMAN_FILTER_BILINEAR:
     579                 :     case PIXMAN_FILTER_GOOD:
     580                 :     case PIXMAN_FILTER_BEST:
     581                 :         return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
     582                 :         break;
     583                 : 
     584                 :     case PIXMAN_FILTER_CONVOLUTION:
     585                 :         return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
     586                 :         break;
     587                 : 
     588                 :     default:
     589                 :         break;
     590                 :     }
     591                 : 
     592               0 :     return 0;
     593                 : }
     594                 : 
     595                 : static void
     596               0 : bits_image_fetch_affine_no_alpha (pixman_image_t * image,
     597                 :                                   int              offset,
     598                 :                                   int              line,
     599                 :                                   int              width,
     600                 :                                   uint32_t *       buffer,
     601                 :                                   const uint32_t * mask)
     602                 : {
     603                 :     pixman_fixed_t x, y;
     604                 :     pixman_fixed_t ux, uy;
     605                 :     pixman_vector_t v;
     606                 :     int i;
     607                 : 
     608                 :     /* reference point is the center of the pixel */
     609               0 :     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
     610               0 :     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
     611               0 :     v.vector[2] = pixman_fixed_1;
     612                 : 
     613               0 :     if (image->common.transform)
     614                 :     {
     615               0 :         if (!pixman_transform_point_3d (image->common.transform, &v))
     616               0 :             return;
     617                 : 
     618               0 :         ux = image->common.transform->matrix[0][0];
     619               0 :         uy = image->common.transform->matrix[1][0];
     620                 :     }
     621                 :     else
     622                 :     {
     623               0 :         ux = pixman_fixed_1;
     624               0 :         uy = 0;
     625                 :     }
     626                 : 
     627               0 :     x = v.vector[0];
     628               0 :     y = v.vector[1];
     629                 : 
     630               0 :     for (i = 0; i < width; ++i)
     631                 :     {
     632               0 :         if (!mask || mask[i])
     633                 :         {
     634               0 :             buffer[i] = bits_image_fetch_pixel_filtered (
     635                 :                 &image->bits, x, y, fetch_pixel_no_alpha);
     636                 :         }
     637                 : 
     638               0 :         x += ux;
     639               0 :         y += uy;
     640                 :     }
     641                 : }
     642                 : 
     643                 : /* General fetcher */
     644                 : static force_inline uint32_t
     645               0 : fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
     646                 : {
     647                 :     uint32_t pixel;
     648                 : 
     649               0 :     if (check_bounds &&
     650               0 :         (x < 0 || x >= image->width || y < 0 || y >= image->height))
     651                 :     {
     652               0 :         return 0;
     653                 :     }
     654                 : 
     655               0 :     pixel = image->fetch_pixel_32 (image, x, y);
     656                 : 
     657               0 :     if (image->common.alpha_map)
     658                 :     {
     659                 :         uint32_t pixel_a;
     660                 : 
     661               0 :         x -= image->common.alpha_origin_x;
     662               0 :         y -= image->common.alpha_origin_y;
     663                 : 
     664               0 :         if (x < 0 || x >= image->common.alpha_map->width ||
     665               0 :             y < 0 || y >= image->common.alpha_map->height)
     666                 :         {
     667               0 :             pixel_a = 0;
     668                 :         }
     669                 :         else
     670                 :         {
     671               0 :             pixel_a = image->common.alpha_map->fetch_pixel_32 (
     672                 :                 image->common.alpha_map, x, y);
     673                 : 
     674               0 :             pixel_a = ALPHA_8 (pixel_a);
     675                 :         }
     676                 : 
     677               0 :         pixel &= 0x00ffffff;
     678               0 :         pixel |= (pixel_a << 24);
     679                 :     }
     680                 : 
     681               0 :     return pixel;
     682                 : }
     683                 : 
     684                 : static void
     685               0 : bits_image_fetch_general (pixman_image_t * image,
     686                 :                           int              offset,
     687                 :                           int              line,
     688                 :                           int              width,
     689                 :                           uint32_t *       buffer,
     690                 :                           const uint32_t * mask)
     691                 : {
     692                 :     pixman_fixed_t x, y, w;
     693                 :     pixman_fixed_t ux, uy, uw;
     694                 :     pixman_vector_t v;
     695                 :     int i;
     696                 : 
     697                 :     /* reference point is the center of the pixel */
     698               0 :     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
     699               0 :     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
     700               0 :     v.vector[2] = pixman_fixed_1;
     701                 : 
     702               0 :     if (image->common.transform)
     703                 :     {
     704               0 :         if (!pixman_transform_point_3d (image->common.transform, &v))
     705               0 :             return;
     706                 : 
     707               0 :         ux = image->common.transform->matrix[0][0];
     708               0 :         uy = image->common.transform->matrix[1][0];
     709               0 :         uw = image->common.transform->matrix[2][0];
     710                 :     }
     711                 :     else
     712                 :     {
     713               0 :         ux = pixman_fixed_1;
     714               0 :         uy = 0;
     715               0 :         uw = 0;
     716                 :     }
     717                 : 
     718               0 :     x = v.vector[0];
     719               0 :     y = v.vector[1];
     720               0 :     w = v.vector[2];
     721                 : 
     722               0 :     for (i = 0; i < width; ++i)
     723                 :     {
     724                 :         pixman_fixed_t x0, y0;
     725                 : 
     726               0 :         if (!mask || mask[i])
     727                 :         {
     728               0 :             if (w != 0)
     729                 :             {
     730               0 :                 x0 = ((pixman_fixed_48_16_t)x << 16) / w;
     731               0 :                 y0 = ((pixman_fixed_48_16_t)y << 16) / w;
     732                 :             }
     733                 :             else
     734                 :             {
     735               0 :                 x0 = 0;
     736               0 :                 y0 = 0;
     737                 :             }
     738                 : 
     739               0 :             buffer[i] = bits_image_fetch_pixel_filtered (
     740                 :                 &image->bits, x0, y0, fetch_pixel_general);
     741                 :         }
     742                 : 
     743               0 :         x += ux;
     744               0 :         y += uy;
     745               0 :         w += uw;
     746                 :     }
     747                 : }
     748                 : 
     749                 : static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
     750                 : 
     751                 : typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
     752                 : 
     753                 : static force_inline void
     754                 : bits_image_fetch_bilinear_affine (pixman_image_t * image,
     755                 :                                   int              offset,
     756                 :                                   int              line,
     757                 :                                   int              width,
     758                 :                                   uint32_t *       buffer,
     759                 :                                   const uint32_t * mask,
     760                 : 
     761                 :                                   convert_pixel_t       convert_pixel,
     762                 :                                   pixman_format_code_t  format,
     763                 :                                   pixman_repeat_t       repeat_mode)
     764                 : {
     765                 :     pixman_fixed_t x, y;
     766                 :     pixman_fixed_t ux, uy;
     767                 :     pixman_vector_t v;
     768               0 :     bits_image_t *bits = &image->bits;
     769                 :     int i;
     770                 : 
     771                 :     /* reference point is the center of the pixel */
     772               0 :     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
     773               0 :     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
     774               0 :     v.vector[2] = pixman_fixed_1;
     775                 : 
     776               0 :     if (!pixman_transform_point_3d (image->common.transform, &v))
     777                 :         return;
     778                 : 
     779               0 :     ux = image->common.transform->matrix[0][0];
     780               0 :     uy = image->common.transform->matrix[1][0];
     781                 : 
     782               0 :     x = v.vector[0];
     783               0 :     y = v.vector[1];
     784                 : 
     785               0 :     for (i = 0; i < width; ++i)
     786                 :     {
     787                 :         int x1, y1, x2, y2;
     788                 :         uint32_t tl, tr, bl, br;
     789                 :         int32_t distx, disty;
     790               0 :         int width = image->bits.width;
     791               0 :         int height = image->bits.height;
     792                 :         const uint8_t *row1;
     793                 :         const uint8_t *row2;
     794                 : 
     795               0 :         if (mask && !mask[i])
     796                 :             goto next;
     797                 : 
     798               0 :         x1 = x - pixman_fixed_1 / 2;
     799               0 :         y1 = y - pixman_fixed_1 / 2;
     800                 : 
     801               0 :         distx = (x1 >> 8) & 0xff;
     802               0 :         disty = (y1 >> 8) & 0xff;
     803                 : 
     804               0 :         y1 = pixman_fixed_to_int (y1);
     805               0 :         y2 = y1 + 1;
     806               0 :         x1 = pixman_fixed_to_int (x1);
     807               0 :         x2 = x1 + 1;
     808                 : 
     809               0 :         if (repeat_mode != PIXMAN_REPEAT_NONE)
     810                 :         {
     811                 :             uint32_t mask;
     812                 : 
     813               0 :             mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
     814                 : 
     815                 :             repeat (repeat_mode, width, &x1);
     816                 :             repeat (repeat_mode, height, &y1);
     817                 :             repeat (repeat_mode, width, &x2);
     818                 :             repeat (repeat_mode, height, &y2);
     819                 : 
     820               0 :             row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
     821               0 :             row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
     822                 : 
     823               0 :             tl = convert_pixel (row1, x1) | mask;
     824               0 :             tr = convert_pixel (row1, x2) | mask;
     825               0 :             bl = convert_pixel (row2, x1) | mask;
     826               0 :             br = convert_pixel (row2, x2) | mask;
     827                 :         }
     828                 :         else
     829                 :         {
     830                 :             uint32_t mask1, mask2;
     831                 :             int bpp;
     832                 : 
     833                 :             /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value,
     834                 :              * which means if you use it in expressions, those
     835                 :              * expressions become unsigned themselves. Since
     836                 :              * the variables below can be negative in some cases,
     837                 :              * that will lead to crashes on 64 bit architectures.
     838                 :              *
     839                 :              * So this line makes sure bpp is signed
     840                 :              */
     841               0 :             bpp = PIXMAN_FORMAT_BPP (format);
     842                 : 
     843               0 :             if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
     844                 :             {
     845               0 :                 buffer[i] = 0;
     846                 :                 goto next;
     847                 :             }
     848                 : 
     849               0 :             if (y2 == 0)
     850                 :             {
     851               0 :                 row1 = zero;
     852               0 :                 mask1 = 0;
     853                 :             }
     854                 :             else
     855                 :             {
     856               0 :                 row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
     857               0 :                 row1 += bpp / 8 * x1;
     858                 : 
     859               0 :                 mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
     860                 :             }
     861                 : 
     862               0 :             if (y1 == height - 1)
     863                 :             {
     864               0 :                 row2 = zero;
     865               0 :                 mask2 = 0;
     866                 :             }
     867                 :             else
     868                 :             {
     869               0 :                 row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
     870               0 :                 row2 += bpp / 8 * x1;
     871                 : 
     872               0 :                 mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
     873                 :             }
     874                 : 
     875               0 :             if (x2 == 0)
     876                 :             {
     877               0 :                 tl = 0;
     878               0 :                 bl = 0;
     879                 :             }
     880                 :             else
     881                 :             {
     882               0 :                 tl = convert_pixel (row1, 0) | mask1;
     883               0 :                 bl = convert_pixel (row2, 0) | mask2;
     884                 :             }
     885                 : 
     886               0 :             if (x1 == width - 1)
     887                 :             {
     888               0 :                 tr = 0;
     889               0 :                 br = 0;
     890                 :             }
     891                 :             else
     892                 :             {
     893               0 :                 tr = convert_pixel (row1, 1) | mask1;
     894               0 :                 br = convert_pixel (row2, 1) | mask2;
     895                 :             }
     896                 :         }
     897                 : 
     898               0 :         buffer[i] = bilinear_interpolation (
     899                 :             tl, tr, bl, br, distx, disty);
     900                 : 
     901                 :     next:
     902               0 :         x += ux;
     903               0 :         y += uy;
     904                 :     }
     905                 : }
     906                 : 
     907                 : static force_inline void
     908                 : bits_image_fetch_nearest_affine (pixman_image_t * image,
     909                 :                                  int              offset,
     910                 :                                  int              line,
     911                 :                                  int              width,
     912                 :                                  uint32_t *       buffer,
     913                 :                                  const uint32_t * mask,
     914                 :                                  
     915                 :                                  convert_pixel_t        convert_pixel,
     916                 :                                  pixman_format_code_t   format,
     917                 :                                  pixman_repeat_t        repeat_mode)
     918                 : {
     919                 :     pixman_fixed_t x, y;
     920                 :     pixman_fixed_t ux, uy;
     921                 :     pixman_vector_t v;
     922               0 :     bits_image_t *bits = &image->bits;
     923                 :     int i;
     924                 : 
     925                 :     /* reference point is the center of the pixel */
     926               0 :     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
     927               0 :     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
     928               0 :     v.vector[2] = pixman_fixed_1;
     929                 : 
     930               0 :     if (!pixman_transform_point_3d (image->common.transform, &v))
     931                 :         return;
     932                 : 
     933               0 :     ux = image->common.transform->matrix[0][0];
     934               0 :     uy = image->common.transform->matrix[1][0];
     935                 : 
     936               0 :     x = v.vector[0];
     937               0 :     y = v.vector[1];
     938                 : 
     939               0 :     for (i = 0; i < width; ++i)
     940                 :     {
     941                 :         int width, height, x0, y0;
     942                 :         const uint8_t *row;
     943                 : 
     944               0 :         if (mask && !mask[i])
     945                 :             goto next;
     946                 :         
     947               0 :         width = image->bits.width;
     948               0 :         height = image->bits.height;
     949               0 :         x0 = pixman_fixed_to_int (x - pixman_fixed_e);
     950               0 :         y0 = pixman_fixed_to_int (y - pixman_fixed_e);
     951                 : 
     952               0 :         if (repeat_mode == PIXMAN_REPEAT_NONE &&
     953               0 :             (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width))
     954                 :         {
     955               0 :             buffer[i] = 0;
     956                 :         }
     957                 :         else
     958                 :         {
     959               0 :             uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
     960                 : 
     961               0 :             if (repeat_mode != PIXMAN_REPEAT_NONE)
     962                 :             {
     963                 :                 repeat (repeat_mode, width, &x0);
     964                 :                 repeat (repeat_mode, height, &y0);
     965                 :             }
     966                 : 
     967               0 :             row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;
     968                 : 
     969               0 :             buffer[i] = convert_pixel (row, x0) | mask;
     970                 :         }
     971                 : 
     972                 :     next:
     973               0 :         x += ux;
     974               0 :         y += uy;
     975                 :     }
     976                 : }
     977                 : 
     978                 : static force_inline uint32_t
     979               0 : convert_a8r8g8b8 (const uint8_t *row, int x)
     980                 : {
     981               0 :     return *(((uint32_t *)row) + x);
     982                 : }
     983                 : 
     984                 : static force_inline uint32_t
     985               0 : convert_x8r8g8b8 (const uint8_t *row, int x)
     986                 : {
     987               0 :     return *(((uint32_t *)row) + x);
     988                 : }
     989                 : 
     990                 : static force_inline uint32_t
     991               0 : convert_a8 (const uint8_t *row, int x)
     992                 : {
     993               0 :     return *(row + x) << 24;
     994                 : }
     995                 : 
     996                 : static force_inline uint32_t
     997               0 : convert_r5g6b5 (const uint8_t *row, int x)
     998                 : {
     999               0 :     return CONVERT_0565_TO_0888 (*((uint16_t *)row + x));
    1000                 : }
    1001                 : 
    1002                 : #define MAKE_BILINEAR_FETCHER(name, format, repeat_mode)                \
    1003                 :     static void                                                         \
    1004                 :     bits_image_fetch_bilinear_affine_ ## name (pixman_image_t *image,   \
    1005                 :                                                int              offset, \
    1006                 :                                                int              line,   \
    1007                 :                                                int              width,  \
    1008                 :                                                uint32_t *       buffer, \
    1009                 :                                                const uint32_t * mask)   \
    1010                 :     {                                                                   \
    1011                 :         bits_image_fetch_bilinear_affine (image, offset, line,          \
    1012                 :                                           width, buffer, mask,          \
    1013                 :                                           convert_ ## format,           \
    1014                 :                                           PIXMAN_ ## format,            \
    1015                 :                                           repeat_mode);                 \
    1016                 :     }
    1017                 : 
    1018                 : #define MAKE_NEAREST_FETCHER(name, format, repeat_mode)                 \
    1019                 :     static void                                                         \
    1020                 :     bits_image_fetch_nearest_affine_ ## name (pixman_image_t *image,    \
    1021                 :                                               int              offset,  \
    1022                 :                                               int              line,    \
    1023                 :                                               int              width,   \
    1024                 :                                               uint32_t *       buffer,  \
    1025                 :                                               const uint32_t * mask)    \
    1026                 :     {                                                                   \
    1027                 :         bits_image_fetch_nearest_affine (image, offset, line,           \
    1028                 :                                          width, buffer, mask,           \
    1029                 :                                          convert_ ## format,            \
    1030                 :                                          PIXMAN_ ## format,             \
    1031                 :                                          repeat_mode);                  \
    1032                 :     }
    1033                 : 
    1034                 : #define MAKE_FETCHERS(name, format, repeat_mode)                        \
    1035                 :     MAKE_NEAREST_FETCHER (name, format, repeat_mode)                    \
    1036                 :     MAKE_BILINEAR_FETCHER (name, format, repeat_mode)
    1037                 : 
    1038               0 : MAKE_FETCHERS (pad_a8r8g8b8,     a8r8g8b8, PIXMAN_REPEAT_PAD)
    1039               0 : MAKE_FETCHERS (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE)
    1040               0 : MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT)
    1041               0 : MAKE_FETCHERS (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL)
    1042               0 : MAKE_FETCHERS (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD)
    1043               0 : MAKE_FETCHERS (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE)
    1044               0 : MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT)
    1045               0 : MAKE_FETCHERS (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL)
    1046               0 : MAKE_FETCHERS (pad_a8,           a8,       PIXMAN_REPEAT_PAD)
    1047               0 : MAKE_FETCHERS (none_a8,          a8,       PIXMAN_REPEAT_NONE)
    1048               0 : MAKE_FETCHERS (reflect_a8,       a8,       PIXMAN_REPEAT_REFLECT)
    1049               0 : MAKE_FETCHERS (normal_a8,        a8,       PIXMAN_REPEAT_NORMAL)
    1050               0 : MAKE_FETCHERS (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD)
    1051               0 : MAKE_FETCHERS (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE)
    1052               0 : MAKE_FETCHERS (reflect_r5g6b5,   r5g6b5,   PIXMAN_REPEAT_REFLECT)
    1053               0 : MAKE_FETCHERS (normal_r5g6b5,    r5g6b5,   PIXMAN_REPEAT_NORMAL)
    1054                 : 
    1055                 : static void
    1056               0 : bits_image_fetch_solid_32 (pixman_image_t * image,
    1057                 :                            int              x,
    1058                 :                            int              y,
    1059                 :                            int              width,
    1060                 :                            uint32_t *       buffer,
    1061                 :                            const uint32_t * mask)
    1062                 : {
    1063                 :     uint32_t color;
    1064                 :     uint32_t *end;
    1065                 : 
    1066               0 :     color = image->bits.fetch_pixel_32 (&image->bits, 0, 0);
    1067                 : 
    1068               0 :     end = buffer + width;
    1069               0 :     while (buffer < end)
    1070               0 :         *(buffer++) = color;
    1071               0 : }
    1072                 : 
    1073                 : static void
    1074               0 : bits_image_fetch_solid_64 (pixman_image_t * image,
    1075                 :                            int              x,
    1076                 :                            int              y,
    1077                 :                            int              width,
    1078                 :                            uint32_t *       b,
    1079                 :                            const uint32_t * unused)
    1080                 : {
    1081                 :     uint64_t color;
    1082               0 :     uint64_t *buffer = (uint64_t *)b;
    1083                 :     uint64_t *end;
    1084                 : 
    1085               0 :     color = image->bits.fetch_pixel_64 (&image->bits, 0, 0);
    1086                 : 
    1087               0 :     end = buffer + width;
    1088               0 :     while (buffer < end)
    1089               0 :         *(buffer++) = color;
    1090               0 : }
    1091                 : 
    1092                 : static void
    1093               0 : bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
    1094                 :                                             pixman_bool_t wide,
    1095                 :                                             int           x,
    1096                 :                                             int           y,
    1097                 :                                             int           width,
    1098                 :                                             uint32_t *    buffer)
    1099                 : {
    1100                 :     uint32_t w;
    1101                 : 
    1102               0 :     if (y < 0 || y >= image->height)
    1103                 :     {
    1104               0 :         memset (buffer, 0, width * (wide? 8 : 4));
    1105               0 :         return;
    1106                 :     }
    1107                 : 
    1108               0 :     if (x < 0)
    1109                 :     {
    1110               0 :         w = MIN (width, -x);
    1111                 : 
    1112               0 :         memset (buffer, 0, w * (wide ? 8 : 4));
    1113                 : 
    1114               0 :         width -= w;
    1115               0 :         buffer += w * (wide? 2 : 1);
    1116               0 :         x += w;
    1117                 :     }
    1118                 : 
    1119               0 :     if (x < image->width)
    1120                 :     {
    1121               0 :         w = MIN (width, image->width - x);
    1122                 : 
    1123               0 :         if (wide)
    1124               0 :             image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
    1125                 :         else
    1126               0 :             image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
    1127                 : 
    1128               0 :         width -= w;
    1129               0 :         buffer += w * (wide? 2 : 1);
    1130               0 :         x += w;
    1131                 :     }
    1132                 : 
    1133               0 :     memset (buffer, 0, width * (wide ? 8 : 4));
    1134                 : }
    1135                 : 
    1136                 : static void
    1137               0 : bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
    1138                 :                                               pixman_bool_t wide,
    1139                 :                                               int           x,
    1140                 :                                               int           y,
    1141                 :                                               int           width,
    1142                 :                                               uint32_t *    buffer)
    1143                 : {
    1144                 :     uint32_t w;
    1145                 : 
    1146               0 :     while (y < 0)
    1147               0 :         y += image->height;
    1148                 : 
    1149               0 :     while (y >= image->height)
    1150               0 :         y -= image->height;
    1151                 : 
    1152               0 :     while (width)
    1153                 :     {
    1154               0 :         while (x < 0)
    1155               0 :             x += image->width;
    1156               0 :         while (x >= image->width)
    1157               0 :             x -= image->width;
    1158                 : 
    1159               0 :         w = MIN (width, image->width - x);
    1160                 : 
    1161               0 :         if (wide)
    1162               0 :             image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
    1163                 :         else
    1164               0 :             image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
    1165                 : 
    1166               0 :         buffer += w * (wide? 2 : 1);
    1167               0 :         x += w;
    1168               0 :         width -= w;
    1169                 :     }
    1170               0 : }
    1171                 : 
    1172                 : static void
    1173               0 : bits_image_fetch_untransformed_32 (pixman_image_t * image,
    1174                 :                                    int              x,
    1175                 :                                    int              y,
    1176                 :                                    int              width,
    1177                 :                                    uint32_t *       buffer,
    1178                 :                                    const uint32_t * mask)
    1179                 : {
    1180               0 :     if (image->common.repeat == PIXMAN_REPEAT_NONE)
    1181                 :     {
    1182               0 :         bits_image_fetch_untransformed_repeat_none (
    1183                 :             &image->bits, FALSE, x, y, width, buffer);
    1184                 :     }
    1185                 :     else
    1186                 :     {
    1187               0 :         bits_image_fetch_untransformed_repeat_normal (
    1188                 :             &image->bits, FALSE, x, y, width, buffer);
    1189                 :     }
    1190               0 : }
    1191                 : 
    1192                 : static void
    1193               0 : bits_image_fetch_untransformed_64 (pixman_image_t * image,
    1194                 :                                    int              x,
    1195                 :                                    int              y,
    1196                 :                                    int              width,
    1197                 :                                    uint32_t *       buffer,
    1198                 :                                    const uint32_t * unused)
    1199                 : {
    1200               0 :     if (image->common.repeat == PIXMAN_REPEAT_NONE)
    1201                 :     {
    1202               0 :         bits_image_fetch_untransformed_repeat_none (
    1203                 :             &image->bits, TRUE, x, y, width, buffer);
    1204                 :     }
    1205                 :     else
    1206                 :     {
    1207               0 :         bits_image_fetch_untransformed_repeat_normal (
    1208                 :             &image->bits, TRUE, x, y, width, buffer);
    1209                 :     }
    1210               0 : }
    1211                 : 
    1212                 : typedef struct
    1213                 : {
    1214                 :     pixman_format_code_t        format;
    1215                 :     uint32_t                    flags;
    1216                 :     fetch_scanline_t            fetch_32;
    1217                 :     fetch_scanline_t            fetch_64;
    1218                 : } fetcher_info_t;
    1219                 : 
    1220                 : static const fetcher_info_t fetcher_info[] =
    1221                 : {
    1222                 :     { PIXMAN_solid,
    1223                 :       FAST_PATH_NO_ALPHA_MAP,
    1224                 :       bits_image_fetch_solid_32,
    1225                 :       bits_image_fetch_solid_64
    1226                 :     },
    1227                 : 
    1228                 :     { PIXMAN_any,
    1229                 :       (FAST_PATH_NO_ALPHA_MAP                   |
    1230                 :        FAST_PATH_ID_TRANSFORM                   |
    1231                 :        FAST_PATH_NO_CONVOLUTION_FILTER          |
    1232                 :        FAST_PATH_NO_PAD_REPEAT                  |
    1233                 :        FAST_PATH_NO_REFLECT_REPEAT),
    1234                 :       bits_image_fetch_untransformed_32,
    1235                 :       bits_image_fetch_untransformed_64
    1236                 :     },
    1237                 : 
    1238                 : #define FAST_BILINEAR_FLAGS                                             \
    1239                 :     (FAST_PATH_NO_ALPHA_MAP             |                               \
    1240                 :      FAST_PATH_NO_ACCESSORS             |                               \
    1241                 :      FAST_PATH_HAS_TRANSFORM            |                               \
    1242                 :      FAST_PATH_AFFINE_TRANSFORM         |                               \
    1243                 :      FAST_PATH_X_UNIT_POSITIVE          |                               \
    1244                 :      FAST_PATH_Y_UNIT_ZERO              |                               \
    1245                 :      FAST_PATH_NONE_REPEAT              |                               \
    1246                 :      FAST_PATH_BILINEAR_FILTER)
    1247                 : 
    1248                 :     { PIXMAN_a8r8g8b8,
    1249                 :       FAST_BILINEAR_FLAGS,
    1250                 :       bits_image_fetch_bilinear_no_repeat_8888,
    1251                 :       _pixman_image_get_scanline_generic_64
    1252                 :     },
    1253                 : 
    1254                 :     { PIXMAN_x8r8g8b8,
    1255                 :       FAST_BILINEAR_FLAGS,
    1256                 :       bits_image_fetch_bilinear_no_repeat_8888,
    1257                 :       _pixman_image_get_scanline_generic_64
    1258                 :     },
    1259                 : 
    1260                 : #define GENERAL_BILINEAR_FLAGS                                          \
    1261                 :     (FAST_PATH_NO_ALPHA_MAP             |                               \
    1262                 :      FAST_PATH_NO_ACCESSORS             |                               \
    1263                 :      FAST_PATH_HAS_TRANSFORM            |                               \
    1264                 :      FAST_PATH_AFFINE_TRANSFORM         |                               \
    1265                 :      FAST_PATH_BILINEAR_FILTER)
    1266                 : 
    1267                 : #define GENERAL_NEAREST_FLAGS                                           \
    1268                 :     (FAST_PATH_NO_ALPHA_MAP             |                               \
    1269                 :      FAST_PATH_NO_ACCESSORS             |                               \
    1270                 :      FAST_PATH_HAS_TRANSFORM            |                               \
    1271                 :      FAST_PATH_AFFINE_TRANSFORM         |                               \
    1272                 :      FAST_PATH_NEAREST_FILTER)
    1273                 : 
    1274                 : #define BILINEAR_AFFINE_FAST_PATH(name, format, repeat)                 \
    1275                 :     { PIXMAN_ ## format,                                                \
    1276                 :       GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT,         \
    1277                 :       bits_image_fetch_bilinear_affine_ ## name,                        \
    1278                 :       _pixman_image_get_scanline_generic_64                             \
    1279                 :     },
    1280                 : 
    1281                 : #define NEAREST_AFFINE_FAST_PATH(name, format, repeat)                  \
    1282                 :     { PIXMAN_ ## format,                                                \
    1283                 :       GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT,          \
    1284                 :       bits_image_fetch_nearest_affine_ ## name,                 \
    1285                 :       _pixman_image_get_scanline_generic_64                             \
    1286                 :     },
    1287                 : 
    1288                 : #define AFFINE_FAST_PATHS(name, format, repeat)                         \
    1289                 :     BILINEAR_AFFINE_FAST_PATH(name, format, repeat)                     \
    1290                 :     NEAREST_AFFINE_FAST_PATH(name, format, repeat)
    1291                 :     
    1292                 :     AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD)
    1293                 :     AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE)
    1294                 :     AFFINE_FAST_PATHS (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
    1295                 :     AFFINE_FAST_PATHS (normal_a8r8g8b8, a8r8g8b8, NORMAL)
    1296                 :     AFFINE_FAST_PATHS (pad_x8r8g8b8, x8r8g8b8, PAD)
    1297                 :     AFFINE_FAST_PATHS (none_x8r8g8b8, x8r8g8b8, NONE)
    1298                 :     AFFINE_FAST_PATHS (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
    1299                 :     AFFINE_FAST_PATHS (normal_x8r8g8b8, x8r8g8b8, NORMAL)
    1300                 :     AFFINE_FAST_PATHS (pad_a8, a8, PAD)
    1301                 :     AFFINE_FAST_PATHS (none_a8, a8, NONE)
    1302                 :     AFFINE_FAST_PATHS (reflect_a8, a8, REFLECT)
    1303                 :     AFFINE_FAST_PATHS (normal_a8, a8, NORMAL)
    1304                 :     AFFINE_FAST_PATHS (pad_r5g6b5, r5g6b5, PAD)
    1305                 :     AFFINE_FAST_PATHS (none_r5g6b5, r5g6b5, NONE)
    1306                 :     AFFINE_FAST_PATHS (reflect_r5g6b5, r5g6b5, REFLECT)
    1307                 :     AFFINE_FAST_PATHS (normal_r5g6b5, r5g6b5, NORMAL)
    1308                 : 
    1309                 :     /* Affine, no alpha */
    1310                 :     { PIXMAN_any,
    1311                 :       (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM),
    1312                 :       bits_image_fetch_affine_no_alpha,
    1313                 :       _pixman_image_get_scanline_generic_64
    1314                 :     },
    1315                 : 
    1316                 :     /* General */
    1317                 :     { PIXMAN_any, 0, bits_image_fetch_general, _pixman_image_get_scanline_generic_64 },
    1318                 : 
    1319                 :     { PIXMAN_null },
    1320                 : };
    1321                 : 
    1322                 : static void
    1323              72 : bits_image_property_changed (pixman_image_t *image)
    1324                 : {
    1325              72 :     uint32_t flags = image->common.flags;
    1326              72 :     pixman_format_code_t format = image->common.extended_format_code;
    1327                 :     const fetcher_info_t *info;
    1328                 : 
    1329              72 :     _pixman_bits_image_setup_accessors (&image->bits);
    1330                 : 
    1331              72 :     info = fetcher_info;
    1332             226 :     while (info->format != PIXMAN_null)
    1333                 :     {
    1334             236 :         if ((info->format == format || info->format == PIXMAN_any)        &&
    1335              82 :             (info->flags & flags) == info->flags)
    1336                 :         {
    1337              72 :             image->bits.get_scanline_32 = info->fetch_32;
    1338              72 :             image->bits.get_scanline_64 = info->fetch_64;
    1339              72 :             break;
    1340                 :         }
    1341                 : 
    1342              82 :         info++;
    1343                 :     }
    1344              72 : }
    1345                 : 
    1346                 : static uint32_t *
    1347               0 : src_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
    1348                 : {
    1349               0 :     iter->image->bits.get_scanline_32 (
    1350               0 :         iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
    1351                 : 
    1352               0 :     return iter->buffer;
    1353                 : }
    1354                 : 
    1355                 : static uint32_t *
    1356               0 : src_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
    1357                 : {
    1358               0 :     iter->image->bits.get_scanline_64 (
    1359               0 :         iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
    1360                 : 
    1361               0 :     return iter->buffer;
    1362                 : }
    1363                 : 
    1364                 : void
    1365               0 : _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter)
    1366                 : {
    1367               0 :     if (iter->flags & ITER_NARROW)
    1368               0 :         iter->get_scanline = src_get_scanline_narrow;
    1369                 :     else
    1370               0 :         iter->get_scanline = src_get_scanline_wide;
    1371               0 : }
    1372                 : 
    1373                 : static uint32_t *
    1374               0 : dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
    1375                 : {
    1376               0 :     pixman_image_t *image  = iter->image;
    1377               0 :     int             x      = iter->x;
    1378               0 :     int             y      = iter->y;
    1379               0 :     int             width  = iter->width;
    1380               0 :     uint32_t *      buffer = iter->buffer;
    1381                 : 
    1382               0 :     image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
    1383               0 :     if (image->common.alpha_map)
    1384                 :     {
    1385               0 :         x -= image->common.alpha_origin_x;
    1386               0 :         y -= image->common.alpha_origin_y;
    1387                 : 
    1388               0 :         image->common.alpha_map->fetch_scanline_32 (
    1389               0 :             (pixman_image_t *)image->common.alpha_map,
    1390                 :             x, y, width, buffer, mask);
    1391                 :     }
    1392                 : 
    1393               0 :     return iter->buffer;
    1394                 : }
    1395                 : 
    1396                 : static uint32_t *
    1397               0 : dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
    1398                 : {
    1399               0 :     bits_image_t *  image  = &iter->image->bits;
    1400               0 :     int             x      = iter->x;
    1401               0 :     int             y      = iter->y;
    1402               0 :     int             width  = iter->width;
    1403               0 :     uint32_t *      buffer = iter->buffer;
    1404                 : 
    1405               0 :     image->fetch_scanline_64 (
    1406                 :         (pixman_image_t *)image, x, y, width, buffer, mask);
    1407               0 :     if (image->common.alpha_map)
    1408                 :     {
    1409               0 :         x -= image->common.alpha_origin_x;
    1410               0 :         y -= image->common.alpha_origin_y;
    1411                 : 
    1412               0 :         image->common.alpha_map->fetch_scanline_64 (
    1413               0 :             (pixman_image_t *)image->common.alpha_map, x, y, width, buffer, mask);
    1414                 :     }
    1415                 : 
    1416               0 :     return iter->buffer;
    1417                 : }
    1418                 : 
    1419                 : static void
    1420               0 : dest_write_back_narrow (pixman_iter_t *iter)
    1421                 : {
    1422               0 :     bits_image_t *  image  = &iter->image->bits;
    1423               0 :     int             x      = iter->x;
    1424               0 :     int             y      = iter->y;
    1425               0 :     int             width  = iter->width;
    1426               0 :     const uint32_t *buffer = iter->buffer;
    1427                 : 
    1428               0 :     image->store_scanline_32 (image, x, y, width, buffer);
    1429                 : 
    1430               0 :     if (image->common.alpha_map)
    1431                 :     {
    1432               0 :         x -= image->common.alpha_origin_x;
    1433               0 :         y -= image->common.alpha_origin_y;
    1434                 : 
    1435               0 :         image->common.alpha_map->store_scanline_32 (
    1436                 :             image->common.alpha_map, x, y, width, buffer);
    1437                 :     }
    1438                 : 
    1439               0 :     iter->y++;
    1440               0 : }
    1441                 : 
    1442                 : static void
    1443               0 : dest_write_back_wide (pixman_iter_t *iter)
    1444                 : {
    1445               0 :     bits_image_t *  image  = &iter->image->bits;
    1446               0 :     int             x      = iter->x;
    1447               0 :     int             y      = iter->y;
    1448               0 :     int             width  = iter->width;
    1449               0 :     const uint32_t *buffer = iter->buffer;
    1450                 : 
    1451               0 :     image->store_scanline_64 (image, x, y, width, buffer);
    1452                 : 
    1453               0 :     if (image->common.alpha_map)
    1454                 :     {
    1455               0 :         x -= image->common.alpha_origin_x;
    1456               0 :         y -= image->common.alpha_origin_y;
    1457                 : 
    1458               0 :         image->common.alpha_map->store_scanline_64 (
    1459                 :             image->common.alpha_map, x, y, width, buffer);
    1460                 :     }
    1461                 : 
    1462               0 :     iter->y++;
    1463               0 : }
    1464                 : 
    1465                 : static void
    1466               0 : dest_write_back_direct (pixman_iter_t *iter)
    1467                 : {
    1468               0 :     iter->buffer += iter->image->bits.rowstride;
    1469               0 : }
    1470                 : 
    1471                 : void
    1472               0 : _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter)
    1473                 : {
    1474               0 :     if (iter->flags & ITER_NARROW)
    1475                 :     {
    1476               0 :         if (((image->common.flags &
    1477                 :               (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_NO_ACCESSORS)) ==
    1478               0 :              (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_NO_ACCESSORS)) &&
    1479               0 :             (image->bits.format == PIXMAN_a8r8g8b8   ||
    1480               0 :              (image->bits.format == PIXMAN_x8r8g8b8  &&
    1481               0 :               (iter->flags & ITER_LOCALIZED_ALPHA))))
    1482                 :         {
    1483               0 :             iter->buffer = image->bits.bits + iter->y * image->bits.rowstride + iter->x;
    1484                 : 
    1485               0 :             iter->get_scanline = _pixman_iter_get_scanline_noop;
    1486               0 :             iter->write_back = dest_write_back_direct;
    1487                 :         }
    1488                 :         else
    1489                 :         {
    1490               0 :             if ((iter->flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
    1491                 :                 (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
    1492                 :             {
    1493               0 :                 iter->get_scanline = _pixman_iter_get_scanline_noop;
    1494                 :             }
    1495                 :             else
    1496                 :             {
    1497               0 :                 iter->get_scanline = dest_get_scanline_narrow;
    1498                 :             }
    1499                 : 
    1500               0 :             iter->write_back = dest_write_back_narrow;
    1501                 :         }
    1502                 :     }
    1503                 :     else
    1504                 :     {
    1505               0 :         iter->get_scanline = dest_get_scanline_wide;
    1506               0 :         iter->write_back = dest_write_back_wide;
    1507                 :     }
    1508               0 : }
    1509                 : 
    1510                 : static uint32_t *
    1511               0 : create_bits (pixman_format_code_t format,
    1512                 :              int                  width,
    1513                 :              int                  height,
    1514                 :              int *                rowstride_bytes)
    1515                 : {
    1516                 :     int stride;
    1517                 :     int buf_size;
    1518                 :     int bpp;
    1519                 : 
    1520                 :     /* what follows is a long-winded way, avoiding any possibility of integer
    1521                 :      * overflows, of saying:
    1522                 :      * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t);
    1523                 :      */
    1524                 : 
    1525               0 :     bpp = PIXMAN_FORMAT_BPP (format);
    1526               0 :     if (pixman_multiply_overflows_int (width, bpp))
    1527               0 :         return NULL;
    1528                 : 
    1529               0 :     stride = width * bpp;
    1530               0 :     if (pixman_addition_overflows_int (stride, 0x1f))
    1531               0 :         return NULL;
    1532                 : 
    1533               0 :     stride += 0x1f;
    1534               0 :     stride >>= 5;
    1535                 : 
    1536               0 :     stride *= sizeof (uint32_t);
    1537                 : 
    1538               0 :     if (pixman_multiply_overflows_int (height, stride))
    1539               0 :         return NULL;
    1540                 : 
    1541               0 :     buf_size = height * stride;
    1542                 : 
    1543               0 :     if (rowstride_bytes)
    1544               0 :         *rowstride_bytes = stride;
    1545                 : 
    1546               0 :     return calloc (buf_size, 1);
    1547                 : }
    1548                 : 
    1549                 : PIXMAN_EXPORT pixman_image_t *
    1550              75 : pixman_image_create_bits (pixman_format_code_t format,
    1551                 :                           int                  width,
    1552                 :                           int                  height,
    1553                 :                           uint32_t *           bits,
    1554                 :                           int                  rowstride_bytes)
    1555                 : {
    1556                 :     pixman_image_t *image;
    1557              75 :     uint32_t *free_me = NULL;
    1558                 : 
    1559                 :     /* must be a whole number of uint32_t's
    1560                 :      */
    1561              75 :     return_val_if_fail (
    1562                 :         bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
    1563                 : 
    1564              75 :     return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
    1565                 : 
    1566              75 :     if (!bits && width && height)
    1567                 :     {
    1568               0 :         free_me = bits = create_bits (format, width, height, &rowstride_bytes);
    1569               0 :         if (!bits)
    1570               0 :             return NULL;
    1571                 :     }
    1572                 : 
    1573              75 :     image = _pixman_image_allocate ();
    1574                 : 
    1575              75 :     if (!image)
    1576                 :     {
    1577               0 :         if (free_me)
    1578               0 :             free (free_me);
    1579                 : 
    1580               0 :         return NULL;
    1581                 :     }
    1582                 : 
    1583              75 :     image->type = BITS;
    1584              75 :     image->bits.format = format;
    1585              75 :     image->bits.width = width;
    1586              75 :     image->bits.height = height;
    1587              75 :     image->bits.bits = bits;
    1588              75 :     image->bits.free_me = free_me;
    1589              75 :     image->bits.read_func = NULL;
    1590              75 :     image->bits.write_func = NULL;
    1591                 : 
    1592                 :     /* The rowstride is stored in number of uint32_t */
    1593              75 :     image->bits.rowstride = rowstride_bytes / (int) sizeof (uint32_t);
    1594                 : 
    1595              75 :     image->bits.indexed = NULL;
    1596                 : 
    1597              75 :     image->common.property_changed = bits_image_property_changed;
    1598                 : 
    1599              75 :     _pixman_image_reset_clip_region (image);
    1600                 : 
    1601              75 :     return image;
    1602                 : }

Generated by: LCOV version 1.7