LCOV - code coverage report
Current view: top level - gfx/cairo/libpixman/src - pixman-bits-image.c (source / functions) Hit Total Coverage
Test: output.info Lines: 29 710 4.1 %
Date: 2017-07-14 16:53:18 Functions: 4 79 5.1 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "pixman-inlines.h"
      38             : 
      39             : static uint32_t *
      40           0 : _pixman_image_get_scanline_generic_float (pixman_iter_t * iter,
      41             :                                           const uint32_t *mask)
      42             : {
      43           0 :     pixman_iter_get_scanline_t fetch_32 = iter->data;
      44           0 :     uint32_t *buffer = iter->buffer;
      45             : 
      46           0 :     fetch_32 (iter, NULL);
      47             : 
      48           0 :     pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
      49             : 
      50           0 :     return iter->buffer;
      51             : }
      52             : 
      53             : /* Fetch functions */
      54             : 
      55             : static force_inline uint32_t
      56           0 : fetch_pixel_no_alpha (bits_image_t *image,
      57             :                       int x, int y, pixman_bool_t check_bounds)
      58             : {
      59           0 :     if (check_bounds &&
      60           0 :         (x < 0 || x >= image->width || y < 0 || y >= image->height))
      61             :     {
      62           0 :         return 0;
      63             :     }
      64             : 
      65           0 :     return image->fetch_pixel_32 (image, x, y);
      66             : }
      67             : 
      68             : typedef uint32_t (* get_pixel_t) (bits_image_t *image,
      69             :                                   int x, int y, pixman_bool_t check_bounds);
      70             : 
      71             : static force_inline uint32_t
      72             : bits_image_fetch_pixel_nearest (bits_image_t   *image,
      73             :                                 pixman_fixed_t  x,
      74             :                                 pixman_fixed_t  y,
      75             :                                 get_pixel_t     get_pixel)
      76             : {
      77           0 :     int x0 = pixman_fixed_to_int (x - pixman_fixed_e);
      78           0 :     int y0 = pixman_fixed_to_int (y - pixman_fixed_e);
      79             : 
      80           0 :     if (image->common.repeat != PIXMAN_REPEAT_NONE)
      81             :     {
      82           0 :         repeat (image->common.repeat, &x0, image->width);
      83           0 :         repeat (image->common.repeat, &y0, image->height);
      84             : 
      85           0 :         return get_pixel (image, x0, y0, FALSE);
      86             :     }
      87             :     else
      88             :     {
      89           0 :         return get_pixel (image, x0, y0, TRUE);
      90             :     }
      91             : }
      92             : 
      93             : static force_inline uint32_t
      94             : bits_image_fetch_pixel_bilinear (bits_image_t   *image,
      95             :                                  pixman_fixed_t  x,
      96             :                                  pixman_fixed_t  y,
      97             :                                  get_pixel_t     get_pixel)
      98             : {
      99           0 :     pixman_repeat_t repeat_mode = image->common.repeat;
     100           0 :     int width = image->width;
     101           0 :     int height = image->height;
     102             :     int x1, y1, x2, y2;
     103             :     uint32_t tl, tr, bl, br;
     104             :     int32_t distx, disty;
     105             : 
     106           0 :     x1 = x - pixman_fixed_1 / 2;
     107           0 :     y1 = y - pixman_fixed_1 / 2;
     108             : 
     109           0 :     distx = pixman_fixed_to_bilinear_weight (x1);
     110           0 :     disty = pixman_fixed_to_bilinear_weight (y1);
     111             : 
     112           0 :     x1 = pixman_fixed_to_int (x1);
     113           0 :     y1 = pixman_fixed_to_int (y1);
     114           0 :     x2 = x1 + 1;
     115           0 :     y2 = y1 + 1;
     116             : 
     117           0 :     if (repeat_mode != PIXMAN_REPEAT_NONE)
     118             :     {
     119             :         repeat (repeat_mode, &x1, width);
     120             :         repeat (repeat_mode, &y1, height);
     121             :         repeat (repeat_mode, &x2, width);
     122             :         repeat (repeat_mode, &y2, height);
     123             : 
     124           0 :         tl = get_pixel (image, x1, y1, FALSE);
     125           0 :         bl = get_pixel (image, x1, y2, FALSE);
     126           0 :         tr = get_pixel (image, x2, y1, FALSE);
     127           0 :         br = get_pixel (image, x2, y2, FALSE);
     128             :     }
     129             :     else
     130             :     {
     131           0 :         tl = get_pixel (image, x1, y1, TRUE);
     132           0 :         tr = get_pixel (image, x2, y1, TRUE);
     133           0 :         bl = get_pixel (image, x1, y2, TRUE);
     134           0 :         br = get_pixel (image, x2, y2, TRUE);
     135             :     }
     136             : 
     137           0 :     return bilinear_interpolation (tl, tr, bl, br, distx, disty);
     138             : }
     139             : 
     140             : static uint32_t *
     141           0 : bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter,
     142             :                                           const uint32_t *mask)
     143             : {
     144             : 
     145           0 :     pixman_image_t * ima = iter->image;
     146           0 :     int              offset = iter->x;
     147           0 :     int              line = iter->y++;
     148           0 :     int              width = iter->width;
     149           0 :     uint32_t *       buffer = iter->buffer;
     150             : 
     151           0 :     bits_image_t *bits = &ima->bits;
     152             :     pixman_fixed_t x_top, x_bottom, x;
     153             :     pixman_fixed_t ux_top, ux_bottom, ux;
     154             :     pixman_vector_t v;
     155             :     uint32_t top_mask, bottom_mask;
     156             :     uint32_t *top_row;
     157             :     uint32_t *bottom_row;
     158             :     uint32_t *end;
     159           0 :     uint32_t zero[2] = { 0, 0 };
     160           0 :     uint32_t one = 1;
     161             :     int y, y1, y2;
     162             :     int disty;
     163             :     int mask_inc;
     164             :     int w;
     165             : 
     166             :     /* reference point is the center of the pixel */
     167           0 :     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
     168           0 :     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
     169           0 :     v.vector[2] = pixman_fixed_1;
     170             : 
     171           0 :     if (!pixman_transform_point_3d (bits->common.transform, &v))
     172           0 :         return iter->buffer;
     173             : 
     174           0 :     ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
     175           0 :     x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
     176             : 
     177           0 :     y = v.vector[1] - pixman_fixed_1/2;
     178           0 :     disty = pixman_fixed_to_bilinear_weight (y);
     179             : 
     180             :     /* Load the pointers to the first and second lines from the source
     181             :      * image that bilinear code must read.
     182             :      *
     183             :      * The main trick in this code is about the check if any line are
     184             :      * outside of the image;
     185             :      *
     186             :      * When I realize that a line (any one) is outside, I change
     187             :      * the pointer to a dummy area with zeros. Once I change this, I
     188             :      * must be sure the pointer will not change, so I set the
     189             :      * variables to each pointer increments inside the loop.
     190             :      */
     191           0 :     y1 = pixman_fixed_to_int (y);
     192           0 :     y2 = y1 + 1;
     193             : 
     194           0 :     if (y1 < 0 || y1 >= bits->height)
     195             :     {
     196           0 :         top_row = zero;
     197           0 :         x_top = 0;
     198           0 :         ux_top = 0;
     199             :     }
     200             :     else
     201             :     {
     202           0 :         top_row = bits->bits + y1 * bits->rowstride;
     203           0 :         x_top = x;
     204           0 :         ux_top = ux;
     205             :     }
     206             : 
     207           0 :     if (y2 < 0 || y2 >= bits->height)
     208             :     {
     209           0 :         bottom_row = zero;
     210           0 :         x_bottom = 0;
     211           0 :         ux_bottom = 0;
     212             :     }
     213             :     else
     214             :     {
     215           0 :         bottom_row = bits->bits + y2 * bits->rowstride;
     216           0 :         x_bottom = x;
     217           0 :         ux_bottom = ux;
     218             :     }
     219             : 
     220             :     /* Instead of checking whether the operation uses the mast in
     221             :      * each loop iteration, verify this only once and prepare the
     222             :      * variables to make the code smaller inside the loop.
     223             :      */
     224           0 :     if (!mask)
     225             :     {
     226           0 :         mask_inc = 0;
     227           0 :         mask = &one;
     228             :     }
     229             :     else
     230             :     {
     231             :         /* If have a mask, prepare the variables to check it */
     232           0 :         mask_inc = 1;
     233             :     }
     234             : 
     235             :     /* If both are zero, then the whole thing is zero */
     236           0 :     if (top_row == zero && bottom_row == zero)
     237             :     {
     238           0 :         memset (buffer, 0, width * sizeof (uint32_t));
     239           0 :         return iter->buffer;
     240             :     }
     241           0 :     else if (bits->format == PIXMAN_x8r8g8b8)
     242             :     {
     243           0 :         if (top_row == zero)
     244             :         {
     245           0 :             top_mask = 0;
     246           0 :             bottom_mask = 0xff000000;
     247             :         }
     248           0 :         else if (bottom_row == zero)
     249             :         {
     250           0 :             top_mask = 0xff000000;
     251           0 :             bottom_mask = 0;
     252             :         }
     253             :         else
     254             :         {
     255           0 :             top_mask = 0xff000000;
     256           0 :             bottom_mask = 0xff000000;
     257             :         }
     258             :     }
     259             :     else
     260             :     {
     261           0 :         top_mask = 0;
     262           0 :         bottom_mask = 0;
     263             :     }
     264             : 
     265           0 :     end = buffer + width;
     266             : 
     267             :     /* Zero fill to the left of the image */
     268           0 :     while (buffer < end && x < pixman_fixed_minus_1)
     269             :     {
     270           0 :         *buffer++ = 0;
     271           0 :         x += ux;
     272           0 :         x_top += ux_top;
     273           0 :         x_bottom += ux_bottom;
     274           0 :         mask += mask_inc;
     275             :     }
     276             : 
     277             :     /* Left edge
     278             :      */
     279           0 :     while (buffer < end && x < 0)
     280             :     {
     281             :         uint32_t tr, br;
     282             :         int32_t distx;
     283             : 
     284           0 :         tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
     285           0 :         br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
     286             : 
     287           0 :         distx = pixman_fixed_to_bilinear_weight (x);
     288             : 
     289           0 :         *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
     290             : 
     291           0 :         x += ux;
     292           0 :         x_top += ux_top;
     293           0 :         x_bottom += ux_bottom;
     294           0 :         mask += mask_inc;
     295             :     }
     296             : 
     297             :     /* Main part */
     298           0 :     w = pixman_int_to_fixed (bits->width - 1);
     299             : 
     300           0 :     while (buffer < end  &&  x < w)
     301             :     {
     302           0 :         if (*mask)
     303             :         {
     304             :             uint32_t tl, tr, bl, br;
     305             :             int32_t distx;
     306             : 
     307           0 :             tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
     308           0 :             tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask;
     309           0 :             bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
     310           0 :             br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
     311             : 
     312           0 :             distx = pixman_fixed_to_bilinear_weight (x);
     313             : 
     314           0 :             *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
     315             :         }
     316             : 
     317           0 :         buffer++;
     318           0 :         x += ux;
     319           0 :         x_top += ux_top;
     320           0 :         x_bottom += ux_bottom;
     321           0 :         mask += mask_inc;
     322             :     }
     323             : 
     324             :     /* Right Edge */
     325           0 :     w = pixman_int_to_fixed (bits->width);
     326           0 :     while (buffer < end  &&  x < w)
     327             :     {
     328           0 :         if (*mask)
     329             :         {
     330             :             uint32_t tl, bl;
     331             :             int32_t distx;
     332             : 
     333           0 :             tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
     334           0 :             bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
     335             : 
     336           0 :             distx = pixman_fixed_to_bilinear_weight (x);
     337             : 
     338           0 :             *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
     339             :         }
     340             : 
     341           0 :         buffer++;
     342           0 :         x += ux;
     343           0 :         x_top += ux_top;
     344           0 :         x_bottom += ux_bottom;
     345           0 :         mask += mask_inc;
     346             :     }
     347             : 
     348             :     /* Zero fill to the left of the image */
     349           0 :     while (buffer < end)
     350           0 :         *buffer++ = 0;
     351             : 
     352           0 :     return iter->buffer;
     353             : }
     354             : 
     355             : static force_inline uint32_t
     356             : bits_image_fetch_pixel_convolution (bits_image_t   *image,
     357             :                                     pixman_fixed_t  x,
     358             :                                     pixman_fixed_t  y,
     359             :                                     get_pixel_t     get_pixel)
     360             : {
     361           0 :     pixman_fixed_t *params = image->common.filter_params;
     362           0 :     int x_off = (params[0] - pixman_fixed_1) >> 1;
     363           0 :     int y_off = (params[1] - pixman_fixed_1) >> 1;
     364           0 :     int32_t cwidth = pixman_fixed_to_int (params[0]);
     365           0 :     int32_t cheight = pixman_fixed_to_int (params[1]);
     366             :     int32_t i, j, x1, x2, y1, y2;
     367           0 :     pixman_repeat_t repeat_mode = image->common.repeat;
     368           0 :     int width = image->width;
     369           0 :     int height = image->height;
     370             :     int srtot, sgtot, sbtot, satot;
     371             : 
     372           0 :     params += 2;
     373             : 
     374           0 :     x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
     375           0 :     y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
     376           0 :     x2 = x1 + cwidth;
     377           0 :     y2 = y1 + cheight;
     378             : 
     379           0 :     srtot = sgtot = sbtot = satot = 0;
     380             : 
     381           0 :     for (i = y1; i < y2; ++i)
     382             :     {
     383           0 :         for (j = x1; j < x2; ++j)
     384             :         {
     385           0 :             int rx = j;
     386           0 :             int ry = i;
     387             : 
     388           0 :             pixman_fixed_t f = *params;
     389             : 
     390           0 :             if (f)
     391             :             {
     392             :                 uint32_t pixel;
     393             : 
     394           0 :                 if (repeat_mode != PIXMAN_REPEAT_NONE)
     395             :                 {
     396             :                     repeat (repeat_mode, &rx, width);
     397             :                     repeat (repeat_mode, &ry, height);
     398             : 
     399           0 :                     pixel = get_pixel (image, rx, ry, FALSE);
     400             :                 }
     401             :                 else
     402             :                 {
     403           0 :                     pixel = get_pixel (image, rx, ry, TRUE);
     404             :                 }
     405             : 
     406           0 :                 srtot += (int)RED_8 (pixel) * f;
     407           0 :                 sgtot += (int)GREEN_8 (pixel) * f;
     408           0 :                 sbtot += (int)BLUE_8 (pixel) * f;
     409           0 :                 satot += (int)ALPHA_8 (pixel) * f;
     410             :             }
     411             : 
     412           0 :             params++;
     413             :         }
     414             :     }
     415             : 
     416           0 :     satot = (satot + 0x8000) >> 16;
     417           0 :     srtot = (srtot + 0x8000) >> 16;
     418           0 :     sgtot = (sgtot + 0x8000) >> 16;
     419           0 :     sbtot = (sbtot + 0x8000) >> 16;
     420             : 
     421           0 :     satot = CLIP (satot, 0, 0xff);
     422           0 :     srtot = CLIP (srtot, 0, 0xff);
     423           0 :     sgtot = CLIP (sgtot, 0, 0xff);
     424           0 :     sbtot = CLIP (sbtot, 0, 0xff);
     425             : 
     426           0 :     return ((satot << 24) | (srtot << 16) | (sgtot <<  8) | (sbtot));
     427             : }
     428             : 
     429             : static uint32_t
     430           0 : bits_image_fetch_pixel_separable_convolution (bits_image_t *image,
     431             :                                               pixman_fixed_t x,
     432             :                                               pixman_fixed_t y,
     433             :                                               get_pixel_t    get_pixel)
     434             : {
     435           0 :     pixman_fixed_t *params = image->common.filter_params;
     436           0 :     pixman_repeat_t repeat_mode = image->common.repeat;
     437           0 :     int width = image->width;
     438           0 :     int height = image->height;
     439           0 :     int cwidth = pixman_fixed_to_int (params[0]);
     440           0 :     int cheight = pixman_fixed_to_int (params[1]);
     441           0 :     int x_phase_bits = pixman_fixed_to_int (params[2]);
     442           0 :     int y_phase_bits = pixman_fixed_to_int (params[3]);
     443           0 :     int x_phase_shift = 16 - x_phase_bits;
     444           0 :     int y_phase_shift = 16 - y_phase_bits;
     445           0 :     int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
     446           0 :     int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
     447             :     pixman_fixed_t *y_params;
     448             :     int srtot, sgtot, sbtot, satot;
     449             :     int32_t x1, x2, y1, y2;
     450             :     int32_t px, py;
     451             :     int i, j;
     452             : 
     453             :     /* Round x and y to the middle of the closest phase before continuing. This
     454             :      * ensures that the convolution matrix is aligned right, since it was
     455             :      * positioned relative to a particular phase (and not relative to whatever
     456             :      * exact fraction we happen to get here).
     457             :      */
     458           0 :     x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
     459           0 :     y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
     460             : 
     461           0 :     px = (x & 0xffff) >> x_phase_shift;
     462           0 :     py = (y & 0xffff) >> y_phase_shift;
     463             : 
     464           0 :     y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
     465             : 
     466           0 :     x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
     467           0 :     y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
     468           0 :     x2 = x1 + cwidth;
     469           0 :     y2 = y1 + cheight;
     470             : 
     471           0 :     srtot = sgtot = sbtot = satot = 0;
     472             : 
     473           0 :     for (i = y1; i < y2; ++i)
     474             :     {
     475           0 :         pixman_fixed_48_16_t fy = *y_params++;
     476           0 :         pixman_fixed_t *x_params = params + 4 + px * cwidth;
     477             : 
     478           0 :         if (fy)
     479             :         {
     480           0 :             for (j = x1; j < x2; ++j)
     481             :             {
     482           0 :                 pixman_fixed_t fx = *x_params++;
     483           0 :                 int rx = j;
     484           0 :                 int ry = i;
     485             : 
     486           0 :                 if (fx)
     487             :                 {
     488             :                     pixman_fixed_t f;
     489             :                     uint32_t pixel;
     490             : 
     491           0 :                     if (repeat_mode != PIXMAN_REPEAT_NONE)
     492             :                     {
     493             :                         repeat (repeat_mode, &rx, width);
     494             :                         repeat (repeat_mode, &ry, height);
     495             : 
     496           0 :                         pixel = get_pixel (image, rx, ry, FALSE);
     497             :                     }
     498             :                     else
     499             :                     {
     500           0 :                         pixel = get_pixel (image, rx, ry, TRUE);
     501             :                     }
     502             : 
     503           0 :                     f = (fy * fx + 0x8000) >> 16;
     504             : 
     505           0 :                     srtot += (int)RED_8 (pixel) * f;
     506           0 :                     sgtot += (int)GREEN_8 (pixel) * f;
     507           0 :                     sbtot += (int)BLUE_8 (pixel) * f;
     508           0 :                     satot += (int)ALPHA_8 (pixel) * f;
     509             :                 }
     510             :             }
     511             :         }
     512             :     }
     513             : 
     514           0 :     satot = (satot + 0x8000) >> 16;
     515           0 :     srtot = (srtot + 0x8000) >> 16;
     516           0 :     sgtot = (sgtot + 0x8000) >> 16;
     517           0 :     sbtot = (sbtot + 0x8000) >> 16;
     518             : 
     519           0 :     satot = CLIP (satot, 0, 0xff);
     520           0 :     srtot = CLIP (srtot, 0, 0xff);
     521           0 :     sgtot = CLIP (sgtot, 0, 0xff);
     522           0 :     sbtot = CLIP (sbtot, 0, 0xff);
     523             : 
     524           0 :     return ((satot << 24) | (srtot << 16) | (sgtot <<  8) | (sbtot));
     525             : }
     526             : 
     527             : static force_inline uint32_t
     528             : bits_image_fetch_pixel_filtered (bits_image_t *image,
     529             :                                  pixman_fixed_t x,
     530             :                                  pixman_fixed_t y,
     531             :                                  get_pixel_t    get_pixel)
     532             : {
     533           0 :     switch (image->common.filter)
     534             :     {
     535             :     case PIXMAN_FILTER_NEAREST:
     536             :     case PIXMAN_FILTER_FAST:
     537           0 :         return bits_image_fetch_pixel_nearest (image, x, y, get_pixel);
     538             :         break;
     539             : 
     540             :     case PIXMAN_FILTER_BILINEAR:
     541             :     case PIXMAN_FILTER_GOOD:
     542             :     case PIXMAN_FILTER_BEST:
     543           0 :         return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
     544             :         break;
     545             : 
     546             :     case PIXMAN_FILTER_CONVOLUTION:
     547           0 :         return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
     548             :         break;
     549             : 
     550             :     case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
     551           0 :         return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel);
     552             :         break;
     553             : 
     554             :     default:
     555             :         break;
     556             :     }
     557             : 
     558           0 :     return 0;
     559             : }
     560             : 
     561             : static uint32_t *
     562           0 : bits_image_fetch_affine_no_alpha (pixman_iter_t *  iter,
     563             :                                   const uint32_t * mask)
     564             : {
     565           0 :     pixman_image_t *image  = iter->image;
     566           0 :     int             offset = iter->x;
     567           0 :     int             line   = iter->y++;
     568           0 :     int             width  = iter->width;
     569           0 :     uint32_t *      buffer = iter->buffer;
     570             : 
     571             :     pixman_fixed_t x, y;
     572             :     pixman_fixed_t ux, uy;
     573             :     pixman_vector_t v;
     574             :     int i;
     575             : 
     576             :     /* reference point is the center of the pixel */
     577           0 :     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
     578           0 :     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
     579           0 :     v.vector[2] = pixman_fixed_1;
     580             : 
     581           0 :     if (image->common.transform)
     582             :     {
     583           0 :         if (!pixman_transform_point_3d (image->common.transform, &v))
     584           0 :             return iter->buffer;
     585             : 
     586           0 :         ux = image->common.transform->matrix[0][0];
     587           0 :         uy = image->common.transform->matrix[1][0];
     588             :     }
     589             :     else
     590             :     {
     591           0 :         ux = pixman_fixed_1;
     592           0 :         uy = 0;
     593             :     }
     594             : 
     595           0 :     x = v.vector[0];
     596           0 :     y = v.vector[1];
     597             : 
     598           0 :     for (i = 0; i < width; ++i)
     599             :     {
     600           0 :         if (!mask || mask[i])
     601             :         {
     602           0 :             buffer[i] = bits_image_fetch_pixel_filtered (
     603             :                 &image->bits, x, y, fetch_pixel_no_alpha);
     604             :         }
     605             : 
     606           0 :         x += ux;
     607           0 :         y += uy;
     608             :     }
     609             : 
     610           0 :     return buffer;
     611             : }
     612             : 
     613             : /* General fetcher */
     614             : static force_inline uint32_t
     615           0 : fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
     616             : {
     617             :     uint32_t pixel;
     618             : 
     619           0 :     if (check_bounds &&
     620           0 :         (x < 0 || x >= image->width || y < 0 || y >= image->height))
     621             :     {
     622           0 :         return 0;
     623             :     }
     624             : 
     625           0 :     pixel = image->fetch_pixel_32 (image, x, y);
     626             : 
     627           0 :     if (image->common.alpha_map)
     628             :     {
     629             :         uint32_t pixel_a;
     630             : 
     631           0 :         x -= image->common.alpha_origin_x;
     632           0 :         y -= image->common.alpha_origin_y;
     633             : 
     634           0 :         if (x < 0 || x >= image->common.alpha_map->width ||
     635           0 :             y < 0 || y >= image->common.alpha_map->height)
     636             :         {
     637           0 :             pixel_a = 0;
     638             :         }
     639             :         else
     640             :         {
     641           0 :             pixel_a = image->common.alpha_map->fetch_pixel_32 (
     642             :                 image->common.alpha_map, x, y);
     643             : 
     644           0 :             pixel_a = ALPHA_8 (pixel_a);
     645             :         }
     646             : 
     647           0 :         pixel &= 0x00ffffff;
     648           0 :         pixel |= (pixel_a << 24);
     649             :     }
     650             : 
     651           0 :     return pixel;
     652             : }
     653             : 
     654             : static uint32_t *
     655           0 : bits_image_fetch_general (pixman_iter_t  *iter,
     656             :                           const uint32_t *mask)
     657             : {
     658           0 :     pixman_image_t *image  = iter->image;
     659           0 :     int             offset = iter->x;
     660           0 :     int             line   = iter->y++;
     661           0 :     int             width  = iter->width;
     662           0 :     uint32_t *      buffer = iter->buffer;
     663             : 
     664             :     pixman_fixed_t x, y, w;
     665             :     pixman_fixed_t ux, uy, uw;
     666             :     pixman_vector_t v;
     667             :     int i;
     668             : 
     669             :     /* reference point is the center of the pixel */
     670           0 :     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
     671           0 :     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
     672           0 :     v.vector[2] = pixman_fixed_1;
     673             : 
     674           0 :     if (image->common.transform)
     675             :     {
     676           0 :         if (!pixman_transform_point_3d (image->common.transform, &v))
     677           0 :             return buffer;
     678             : 
     679           0 :         ux = image->common.transform->matrix[0][0];
     680           0 :         uy = image->common.transform->matrix[1][0];
     681           0 :         uw = image->common.transform->matrix[2][0];
     682             :     }
     683             :     else
     684             :     {
     685           0 :         ux = pixman_fixed_1;
     686           0 :         uy = 0;
     687           0 :         uw = 0;
     688             :     }
     689             : 
     690           0 :     x = v.vector[0];
     691           0 :     y = v.vector[1];
     692           0 :     w = v.vector[2];
     693             : 
     694           0 :     for (i = 0; i < width; ++i)
     695             :     {
     696             :         pixman_fixed_t x0, y0;
     697             : 
     698           0 :         if (!mask || mask[i])
     699             :         {
     700           0 :             if (w != 0)
     701             :             {
     702           0 :                 x0 = ((pixman_fixed_48_16_t)x << 16) / w;
     703           0 :                 y0 = ((pixman_fixed_48_16_t)y << 16) / w;
     704             :             }
     705             :             else
     706             :             {
     707           0 :                 x0 = 0;
     708           0 :                 y0 = 0;
     709             :             }
     710             : 
     711           0 :             buffer[i] = bits_image_fetch_pixel_filtered (
     712             :                 &image->bits, x0, y0, fetch_pixel_general);
     713             :         }
     714             : 
     715           0 :         x += ux;
     716           0 :         y += uy;
     717           0 :         w += uw;
     718             :     }
     719             : 
     720           0 :     return buffer;
     721             : }
     722             : 
     723             : typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
     724             : 
     725             : static force_inline void
     726             : bits_image_fetch_separable_convolution_affine (pixman_image_t * image,
     727             :                                                int              offset,
     728             :                                                int              line,
     729             :                                                int              width,
     730             :                                                uint32_t *       buffer,
     731             :                                                const uint32_t * mask,
     732             : 
     733             :                                                convert_pixel_t  convert_pixel,
     734             :                                                pixman_format_code_t     format,
     735             :                                                pixman_repeat_t  repeat_mode)
     736             : {
     737           0 :     bits_image_t *bits = &image->bits;
     738           0 :     pixman_fixed_t *params = image->common.filter_params;
     739           0 :     int cwidth = pixman_fixed_to_int (params[0]);
     740           0 :     int cheight = pixman_fixed_to_int (params[1]);
     741           0 :     int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
     742           0 :     int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
     743           0 :     int x_phase_bits = pixman_fixed_to_int (params[2]);
     744           0 :     int y_phase_bits = pixman_fixed_to_int (params[3]);
     745           0 :     int x_phase_shift = 16 - x_phase_bits;
     746           0 :     int y_phase_shift = 16 - y_phase_bits;
     747             :     pixman_fixed_t vx, vy;
     748             :     pixman_fixed_t ux, uy;
     749             :     pixman_vector_t v;
     750             :     int k;
     751             : 
     752             :     /* reference point is the center of the pixel */
     753           0 :     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
     754           0 :     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
     755           0 :     v.vector[2] = pixman_fixed_1;
     756             : 
     757           0 :     if (!pixman_transform_point_3d (image->common.transform, &v))
     758           0 :         return;
     759             : 
     760           0 :     ux = image->common.transform->matrix[0][0];
     761           0 :     uy = image->common.transform->matrix[1][0];
     762             : 
     763           0 :     vx = v.vector[0];
     764           0 :     vy = v.vector[1];
     765             : 
     766           0 :     for (k = 0; k < width; ++k)
     767             :     {
     768             :         pixman_fixed_t *y_params;
     769             :         int satot, srtot, sgtot, sbtot;
     770             :         pixman_fixed_t x, y;
     771             :         int32_t x1, x2, y1, y2;
     772             :         int32_t px, py;
     773             :         int i, j;
     774             : 
     775           0 :         if (mask && !mask[k])
     776             :             goto next;
     777             : 
     778             :         /* Round x and y to the middle of the closest phase before continuing. This
     779             :          * ensures that the convolution matrix is aligned right, since it was
     780             :          * positioned relative to a particular phase (and not relative to whatever
     781             :          * exact fraction we happen to get here).
     782             :          */
     783           0 :         x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
     784           0 :         y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
     785             : 
     786           0 :         px = (x & 0xffff) >> x_phase_shift;
     787           0 :         py = (y & 0xffff) >> y_phase_shift;
     788             : 
     789           0 :         x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
     790           0 :         y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
     791           0 :         x2 = x1 + cwidth;
     792           0 :         y2 = y1 + cheight;
     793             : 
     794           0 :         satot = srtot = sgtot = sbtot = 0;
     795             : 
     796           0 :         y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
     797             : 
     798           0 :         for (i = y1; i < y2; ++i)
     799             :         {
     800           0 :             pixman_fixed_t fy = *y_params++;
     801             : 
     802           0 :             if (fy)
     803             :             {
     804           0 :                 pixman_fixed_t *x_params = params + 4 + px * cwidth;
     805             : 
     806           0 :                 for (j = x1; j < x2; ++j)
     807             :                 {
     808           0 :                     pixman_fixed_t fx = *x_params++;
     809           0 :                     int rx = j;
     810           0 :                     int ry = i;
     811             :                     
     812           0 :                     if (fx)
     813             :                     {
     814             :                         pixman_fixed_t f;
     815             :                         uint32_t pixel, mask;
     816             :                         uint8_t *row;
     817             : 
     818           0 :                         mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
     819             : 
     820           0 :                         if (repeat_mode != PIXMAN_REPEAT_NONE)
     821             :                         {
     822           0 :                             repeat (repeat_mode, &rx, bits->width);
     823           0 :                             repeat (repeat_mode, &ry, bits->height);
     824             : 
     825           0 :                             row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
     826           0 :                             pixel = convert_pixel (row, rx) | mask;
     827             :                         }
     828             :                         else
     829             :                         {
     830           0 :                             if (rx < 0 || ry < 0 || rx >= bits->width || ry >= bits->height)
     831             :                             {
     832           0 :                                 pixel = 0;
     833             :                             }
     834             :                             else
     835             :                             {
     836           0 :                                 row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
     837           0 :                                 pixel = convert_pixel (row, rx) | mask;
     838             :                             }
     839             :                         }
     840             : 
     841           0 :                         f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16;
     842           0 :                         srtot += (int)RED_8 (pixel) * f;
     843           0 :                         sgtot += (int)GREEN_8 (pixel) * f;
     844           0 :                         sbtot += (int)BLUE_8 (pixel) * f;
     845           0 :                         satot += (int)ALPHA_8 (pixel) * f;
     846             :                     }
     847             :                 }
     848             :             }
     849             :         }
     850             : 
     851           0 :         satot = (satot + 0x8000) >> 16;
     852           0 :         srtot = (srtot + 0x8000) >> 16;
     853           0 :         sgtot = (sgtot + 0x8000) >> 16;
     854           0 :         sbtot = (sbtot + 0x8000) >> 16;
     855             : 
     856           0 :         satot = CLIP (satot, 0, 0xff);
     857           0 :         srtot = CLIP (srtot, 0, 0xff);
     858           0 :         sgtot = CLIP (sgtot, 0, 0xff);
     859           0 :         sbtot = CLIP (sbtot, 0, 0xff);
     860             : 
     861           0 :         buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0);
     862             : 
     863             :     next:
     864           0 :         vx += ux;
     865           0 :         vy += uy;
     866             :     }
     867             : }
     868             : 
     869             : static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
     870             : 
     871             : static force_inline void
     872             : bits_image_fetch_bilinear_affine (pixman_image_t * image,
     873             :                                   int              offset,
     874             :                                   int              line,
     875             :                                   int              width,
     876             :                                   uint32_t *       buffer,
     877             :                                   const uint32_t * mask,
     878             : 
     879             :                                   convert_pixel_t       convert_pixel,
     880             :                                   pixman_format_code_t  format,
     881             :                                   pixman_repeat_t       repeat_mode)
     882             : {
     883             :     pixman_fixed_t x, y;
     884             :     pixman_fixed_t ux, uy;
     885             :     pixman_vector_t v;
     886           0 :     bits_image_t *bits = &image->bits;
     887             :     int i;
     888             : 
     889             :     /* reference point is the center of the pixel */
     890           0 :     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
     891           0 :     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
     892           0 :     v.vector[2] = pixman_fixed_1;
     893             : 
     894           0 :     if (!pixman_transform_point_3d (image->common.transform, &v))
     895           0 :         return;
     896             : 
     897           0 :     ux = image->common.transform->matrix[0][0];
     898           0 :     uy = image->common.transform->matrix[1][0];
     899             : 
     900           0 :     x = v.vector[0];
     901           0 :     y = v.vector[1];
     902             : 
     903           0 :     for (i = 0; i < width; ++i)
     904             :     {
     905             :         int x1, y1, x2, y2;
     906             :         uint32_t tl, tr, bl, br;
     907             :         int32_t distx, disty;
     908           0 :         int width = image->bits.width;
     909           0 :         int height = image->bits.height;
     910             :         const uint8_t *row1;
     911             :         const uint8_t *row2;
     912             : 
     913           0 :         if (mask && !mask[i])
     914             :             goto next;
     915             : 
     916           0 :         x1 = x - pixman_fixed_1 / 2;
     917           0 :         y1 = y - pixman_fixed_1 / 2;
     918             : 
     919           0 :         distx = pixman_fixed_to_bilinear_weight (x1);
     920           0 :         disty = pixman_fixed_to_bilinear_weight (y1);
     921             : 
     922           0 :         y1 = pixman_fixed_to_int (y1);
     923           0 :         y2 = y1 + 1;
     924           0 :         x1 = pixman_fixed_to_int (x1);
     925           0 :         x2 = x1 + 1;
     926             : 
     927           0 :         if (repeat_mode != PIXMAN_REPEAT_NONE)
     928             :         {
     929             :             uint32_t mask;
     930             : 
     931           0 :             mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
     932             : 
     933             :             repeat (repeat_mode, &x1, width);
     934             :             repeat (repeat_mode, &y1, height);
     935             :             repeat (repeat_mode, &x2, width);
     936             :             repeat (repeat_mode, &y2, height);
     937             : 
     938           0 :             row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
     939           0 :             row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
     940             : 
     941           0 :             tl = convert_pixel (row1, x1) | mask;
     942           0 :             tr = convert_pixel (row1, x2) | mask;
     943           0 :             bl = convert_pixel (row2, x1) | mask;
     944           0 :             br = convert_pixel (row2, x2) | mask;
     945             :         }
     946             :         else
     947             :         {
     948             :             uint32_t mask1, mask2;
     949             :             int bpp;
     950             : 
     951             :             /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value,
     952             :              * which means if you use it in expressions, those
     953             :              * expressions become unsigned themselves. Since
     954             :              * the variables below can be negative in some cases,
     955             :              * that will lead to crashes on 64 bit architectures.
     956             :              *
     957             :              * So this line makes sure bpp is signed
     958             :              */
     959           0 :             bpp = PIXMAN_FORMAT_BPP (format);
     960             : 
     961           0 :             if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
     962             :             {
     963           0 :                 buffer[i] = 0;
     964             :                 goto next;
     965             :             }
     966             : 
     967           0 :             if (y2 == 0)
     968             :             {
     969           0 :                 row1 = zero;
     970           0 :                 mask1 = 0;
     971             :             }
     972             :             else
     973             :             {
     974           0 :                 row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
     975           0 :                 row1 += bpp / 8 * x1;
     976             : 
     977           0 :                 mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
     978             :             }
     979             : 
     980           0 :             if (y1 == height - 1)
     981             :             {
     982           0 :                 row2 = zero;
     983           0 :                 mask2 = 0;
     984             :             }
     985             :             else
     986             :             {
     987           0 :                 row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
     988           0 :                 row2 += bpp / 8 * x1;
     989             : 
     990           0 :                 mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
     991             :             }
     992             : 
     993           0 :             if (x2 == 0)
     994             :             {
     995           0 :                 tl = 0;
     996           0 :                 bl = 0;
     997             :             }
     998             :             else
     999             :             {
    1000           0 :                 tl = convert_pixel (row1, 0) | mask1;
    1001           0 :                 bl = convert_pixel (row2, 0) | mask2;
    1002             :             }
    1003             : 
    1004           0 :             if (x1 == width - 1)
    1005             :             {
    1006           0 :                 tr = 0;
    1007           0 :                 br = 0;
    1008             :             }
    1009             :             else
    1010             :             {
    1011           0 :                 tr = convert_pixel (row1, 1) | mask1;
    1012           0 :                 br = convert_pixel (row2, 1) | mask2;
    1013             :             }
    1014             :         }
    1015             : 
    1016           0 :         buffer[i] = bilinear_interpolation (
    1017             :             tl, tr, bl, br, distx, disty);
    1018             : 
    1019             :     next:
    1020           0 :         x += ux;
    1021           0 :         y += uy;
    1022             :     }
    1023             : }
    1024             : 
    1025             : static force_inline void
    1026             : bits_image_fetch_nearest_affine (pixman_image_t * image,
    1027             :                                  int              offset,
    1028             :                                  int              line,
    1029             :                                  int              width,
    1030             :                                  uint32_t *       buffer,
    1031             :                                  const uint32_t * mask,
    1032             :                                  
    1033             :                                  convert_pixel_t        convert_pixel,
    1034             :                                  pixman_format_code_t   format,
    1035             :                                  pixman_repeat_t        repeat_mode)
    1036             : {
    1037             :     pixman_fixed_t x, y;
    1038             :     pixman_fixed_t ux, uy;
    1039             :     pixman_vector_t v;
    1040           0 :     bits_image_t *bits = &image->bits;
    1041             :     int i;
    1042             : 
    1043             :     /* reference point is the center of the pixel */
    1044           0 :     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
    1045           0 :     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
    1046           0 :     v.vector[2] = pixman_fixed_1;
    1047             : 
    1048           0 :     if (!pixman_transform_point_3d (image->common.transform, &v))
    1049           0 :         return;
    1050             : 
    1051           0 :     ux = image->common.transform->matrix[0][0];
    1052           0 :     uy = image->common.transform->matrix[1][0];
    1053             : 
    1054           0 :     x = v.vector[0];
    1055           0 :     y = v.vector[1];
    1056             : 
    1057           0 :     for (i = 0; i < width; ++i)
    1058             :     {
    1059             :         int width, height, x0, y0;
    1060             :         const uint8_t *row;
    1061             : 
    1062           0 :         if (mask && !mask[i])
    1063             :             goto next;
    1064             :         
    1065           0 :         width = image->bits.width;
    1066           0 :         height = image->bits.height;
    1067           0 :         x0 = pixman_fixed_to_int (x - pixman_fixed_e);
    1068           0 :         y0 = pixman_fixed_to_int (y - pixman_fixed_e);
    1069             : 
    1070           0 :         if (repeat_mode == PIXMAN_REPEAT_NONE &&
    1071           0 :             (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width))
    1072             :         {
    1073           0 :             buffer[i] = 0;
    1074             :         }
    1075             :         else
    1076             :         {
    1077           0 :             uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
    1078             : 
    1079           0 :             if (repeat_mode != PIXMAN_REPEAT_NONE)
    1080             :             {
    1081             :                 repeat (repeat_mode, &x0, width);
    1082             :                 repeat (repeat_mode, &y0, height);
    1083             :             }
    1084             : 
    1085           0 :             row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;
    1086             : 
    1087           0 :             buffer[i] = convert_pixel (row, x0) | mask;
    1088             :         }
    1089             : 
    1090             :     next:
    1091           0 :         x += ux;
    1092           0 :         y += uy;
    1093             :     }
    1094             : }
    1095             : 
    1096             : static force_inline uint32_t
    1097           0 : convert_a8r8g8b8 (const uint8_t *row, int x)
    1098             : {
    1099           0 :     return *(((uint32_t *)row) + x);
    1100             : }
    1101             : 
    1102             : static force_inline uint32_t
    1103           0 : convert_x8r8g8b8 (const uint8_t *row, int x)
    1104             : {
    1105           0 :     return *(((uint32_t *)row) + x);
    1106             : }
    1107             : 
    1108             : static force_inline uint32_t
    1109           0 : convert_a8 (const uint8_t *row, int x)
    1110             : {
    1111           0 :     return *(row + x) << 24;
    1112             : }
    1113             : 
    1114             : static force_inline uint32_t
    1115           0 : convert_r5g6b5 (const uint8_t *row, int x)
    1116             : {
    1117           0 :     return convert_0565_to_0888 (*((uint16_t *)row + x));
    1118             : }
    1119             : 
    1120             : #define MAKE_SEPARABLE_CONVOLUTION_FETCHER(name, format, repeat_mode)  \
    1121             :     static uint32_t *                                                   \
    1122             :     bits_image_fetch_separable_convolution_affine_ ## name (pixman_iter_t   *iter, \
    1123             :                                                             const uint32_t * mask) \
    1124             :     {                                                                   \
    1125             :         bits_image_fetch_separable_convolution_affine (                 \
    1126             :             iter->image,                                                \
    1127             :             iter->x, iter->y++,                                         \
    1128             :             iter->width,                                                \
    1129             :             iter->buffer, mask,                                         \
    1130             :             convert_ ## format,                                         \
    1131             :             PIXMAN_ ## format,                                          \
    1132             :             repeat_mode);                                               \
    1133             :                                                                         \
    1134             :         return iter->buffer;                                            \
    1135             :     }
    1136             : 
    1137             : #define MAKE_BILINEAR_FETCHER(name, format, repeat_mode)                \
    1138             :     static uint32_t *                                                   \
    1139             :     bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t   *iter,   \
    1140             :                                                const uint32_t * mask)   \
    1141             :     {                                                                   \
    1142             :         bits_image_fetch_bilinear_affine (iter->image,                       \
    1143             :                                           iter->x, iter->y++,             \
    1144             :                                           iter->width,                       \
    1145             :                                           iter->buffer, mask,                \
    1146             :                                           convert_ ## format,           \
    1147             :                                           PIXMAN_ ## format,            \
    1148             :                                           repeat_mode);                 \
    1149             :         return iter->buffer;                                         \
    1150             :     }
    1151             : 
    1152             : #define MAKE_NEAREST_FETCHER(name, format, repeat_mode)                 \
    1153             :     static uint32_t *                                                   \
    1154             :     bits_image_fetch_nearest_affine_ ## name (pixman_iter_t   *iter,    \
    1155             :                                               const uint32_t * mask)    \
    1156             :     {                                                                   \
    1157             :         bits_image_fetch_nearest_affine (iter->image,                        \
    1158             :                                          iter->x, iter->y++,              \
    1159             :                                          iter->width,                        \
    1160             :                                          iter->buffer, mask,         \
    1161             :                                          convert_ ## format,            \
    1162             :                                          PIXMAN_ ## format,             \
    1163             :                                          repeat_mode);                  \
    1164             :         return iter->buffer;                                         \
    1165             :     }
    1166             : 
    1167             : #define MAKE_FETCHERS(name, format, repeat_mode)                        \
    1168             :     MAKE_NEAREST_FETCHER (name, format, repeat_mode)                    \
    1169             :     MAKE_BILINEAR_FETCHER (name, format, repeat_mode)                   \
    1170             :     MAKE_SEPARABLE_CONVOLUTION_FETCHER (name, format, repeat_mode)
    1171             : 
    1172           0 : MAKE_FETCHERS (pad_a8r8g8b8,     a8r8g8b8, PIXMAN_REPEAT_PAD)
    1173           0 : MAKE_FETCHERS (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE)
    1174           0 : MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT)
    1175           0 : MAKE_FETCHERS (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL)
    1176           0 : MAKE_FETCHERS (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD)
    1177           0 : MAKE_FETCHERS (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE)
    1178           0 : MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT)
    1179           0 : MAKE_FETCHERS (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL)
    1180           0 : MAKE_FETCHERS (pad_a8,           a8,       PIXMAN_REPEAT_PAD)
    1181           0 : MAKE_FETCHERS (none_a8,          a8,       PIXMAN_REPEAT_NONE)
    1182           0 : MAKE_FETCHERS (reflect_a8,       a8,       PIXMAN_REPEAT_REFLECT)
    1183           0 : MAKE_FETCHERS (normal_a8,        a8,       PIXMAN_REPEAT_NORMAL)
    1184           0 : MAKE_FETCHERS (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD)
    1185           0 : MAKE_FETCHERS (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE)
    1186           0 : MAKE_FETCHERS (reflect_r5g6b5,   r5g6b5,   PIXMAN_REPEAT_REFLECT)
    1187           0 : MAKE_FETCHERS (normal_r5g6b5,    r5g6b5,   PIXMAN_REPEAT_NORMAL)
    1188             : 
    1189             : static void
    1190           0 : replicate_pixel_32 (bits_image_t *   bits,
    1191             :                     int              x,
    1192             :                     int              y,
    1193             :                     int              width,
    1194             :                     uint32_t *       buffer)
    1195             : {
    1196             :     uint32_t color;
    1197             :     uint32_t *end;
    1198             : 
    1199           0 :     color = bits->fetch_pixel_32 (bits, x, y);
    1200             : 
    1201           0 :     end = buffer + width;
    1202           0 :     while (buffer < end)
    1203           0 :         *(buffer++) = color;
    1204           0 : }
    1205             : 
    1206             : static void
    1207           0 : replicate_pixel_float (bits_image_t *   bits,
    1208             :                        int              x,
    1209             :                        int              y,
    1210             :                        int              width,
    1211             :                        uint32_t *       b)
    1212             : {
    1213             :     argb_t color;
    1214           0 :     argb_t *buffer = (argb_t *)b;
    1215             :     argb_t *end;
    1216             : 
    1217           0 :     color = bits->fetch_pixel_float (bits, x, y);
    1218             : 
    1219           0 :     end = buffer + width;
    1220           0 :     while (buffer < end)
    1221           0 :         *(buffer++) = color;
    1222           0 : }
    1223             : 
    1224             : static void
    1225           0 : bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
    1226             :                                             pixman_bool_t wide,
    1227             :                                             int           x,
    1228             :                                             int           y,
    1229             :                                             int           width,
    1230             :                                             uint32_t *    buffer)
    1231             : {
    1232             :     uint32_t w;
    1233             : 
    1234           0 :     if (y < 0 || y >= image->height)
    1235             :     {
    1236           0 :         memset (buffer, 0, width * (wide? sizeof (argb_t) : 4));
    1237           0 :         return;
    1238             :     }
    1239             : 
    1240           0 :     if (x < 0)
    1241             :     {
    1242           0 :         w = MIN (width, -x);
    1243             : 
    1244           0 :         memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4));
    1245             : 
    1246           0 :         width -= w;
    1247           0 :         buffer += w * (wide? 4 : 1);
    1248           0 :         x += w;
    1249             :     }
    1250             : 
    1251           0 :     if (x < image->width)
    1252             :     {
    1253           0 :         w = MIN (width, image->width - x);
    1254             : 
    1255           0 :         if (wide)
    1256           0 :             image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
    1257             :         else
    1258           0 :             image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
    1259             : 
    1260           0 :         width -= w;
    1261           0 :         buffer += w * (wide? 4 : 1);
    1262           0 :         x += w;
    1263             :     }
    1264             : 
    1265           0 :     memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4));
    1266             : }
    1267             : 
    1268             : static void
    1269           0 : bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
    1270             :                                               pixman_bool_t wide,
    1271             :                                               int           x,
    1272             :                                               int           y,
    1273             :                                               int           width,
    1274             :                                               uint32_t *    buffer)
    1275             : {
    1276             :     uint32_t w;
    1277             : 
    1278           0 :     while (y < 0)
    1279           0 :         y += image->height;
    1280             : 
    1281           0 :     while (y >= image->height)
    1282           0 :         y -= image->height;
    1283             : 
    1284           0 :     if (image->width == 1)
    1285             :     {
    1286           0 :         if (wide)
    1287           0 :             replicate_pixel_float (image, 0, y, width, buffer);
    1288             :         else
    1289           0 :             replicate_pixel_32 (image, 0, y, width, buffer);
    1290             : 
    1291           0 :         return;
    1292             :     }
    1293             : 
    1294           0 :     while (width)
    1295             :     {
    1296           0 :         while (x < 0)
    1297           0 :             x += image->width;
    1298           0 :         while (x >= image->width)
    1299           0 :             x -= image->width;
    1300             : 
    1301           0 :         w = MIN (width, image->width - x);
    1302             : 
    1303           0 :         if (wide)
    1304           0 :             image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
    1305             :         else
    1306           0 :             image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
    1307             : 
    1308           0 :         buffer += w * (wide? 4 : 1);
    1309           0 :         x += w;
    1310           0 :         width -= w;
    1311             :     }
    1312             : }
    1313             : 
    1314             : static uint32_t *
    1315           0 : bits_image_fetch_untransformed_32 (pixman_iter_t * iter,
    1316             :                                    const uint32_t *mask)
    1317             : {
    1318           0 :     pixman_image_t *image  = iter->image;
    1319           0 :     int             x      = iter->x;
    1320           0 :     int             y      = iter->y;
    1321           0 :     int             width  = iter->width;
    1322           0 :     uint32_t *      buffer = iter->buffer;
    1323             : 
    1324           0 :     if (image->common.repeat == PIXMAN_REPEAT_NONE)
    1325             :     {
    1326           0 :         bits_image_fetch_untransformed_repeat_none (
    1327             :             &image->bits, FALSE, x, y, width, buffer);
    1328             :     }
    1329             :     else
    1330             :     {
    1331           0 :         bits_image_fetch_untransformed_repeat_normal (
    1332             :             &image->bits, FALSE, x, y, width, buffer);
    1333             :     }
    1334             : 
    1335           0 :     iter->y++;
    1336           0 :     return buffer;
    1337             : }
    1338             : 
    1339             : static uint32_t *
    1340           0 : bits_image_fetch_untransformed_float (pixman_iter_t * iter,
    1341             :                                       const uint32_t *mask)
    1342             : {
    1343           0 :     pixman_image_t *image  = iter->image;
    1344           0 :     int             x      = iter->x;
    1345           0 :     int             y      = iter->y;
    1346           0 :     int             width  = iter->width;
    1347           0 :     uint32_t *      buffer = iter->buffer;
    1348             : 
    1349           0 :     if (image->common.repeat == PIXMAN_REPEAT_NONE)
    1350             :     {
    1351           0 :         bits_image_fetch_untransformed_repeat_none (
    1352             :             &image->bits, TRUE, x, y, width, buffer);
    1353             :     }
    1354             :     else
    1355             :     {
    1356           0 :         bits_image_fetch_untransformed_repeat_normal (
    1357             :             &image->bits, TRUE, x, y, width, buffer);
    1358             :     }
    1359             : 
    1360           0 :     iter->y++;
    1361           0 :     return buffer;
    1362             : }
    1363             : 
    1364             : typedef struct
    1365             : {
    1366             :     pixman_format_code_t        format;
    1367             :     uint32_t                    flags;
    1368             :     pixman_iter_get_scanline_t  get_scanline_32;
    1369             :     pixman_iter_get_scanline_t  get_scanline_float;
    1370             : } fetcher_info_t;
    1371             : 
    1372             : static const fetcher_info_t fetcher_info[] =
    1373             : {
    1374             :     { PIXMAN_any,
    1375             :       (FAST_PATH_NO_ALPHA_MAP                   |
    1376             :        FAST_PATH_ID_TRANSFORM                   |
    1377             :        FAST_PATH_NO_CONVOLUTION_FILTER          |
    1378             :        FAST_PATH_NO_PAD_REPEAT                  |
    1379             :        FAST_PATH_NO_REFLECT_REPEAT),
    1380             :       bits_image_fetch_untransformed_32,
    1381             :       bits_image_fetch_untransformed_float
    1382             :     },
    1383             : 
    1384             : #define FAST_BILINEAR_FLAGS                                             \
    1385             :     (FAST_PATH_NO_ALPHA_MAP             |                               \
    1386             :      FAST_PATH_NO_ACCESSORS             |                               \
    1387             :      FAST_PATH_HAS_TRANSFORM            |                               \
    1388             :      FAST_PATH_AFFINE_TRANSFORM         |                               \
    1389             :      FAST_PATH_X_UNIT_POSITIVE          |                               \
    1390             :      FAST_PATH_Y_UNIT_ZERO              |                               \
    1391             :      FAST_PATH_NONE_REPEAT              |                               \
    1392             :      FAST_PATH_BILINEAR_FILTER)
    1393             : 
    1394             :     { PIXMAN_a8r8g8b8,
    1395             :       FAST_BILINEAR_FLAGS,
    1396             :       bits_image_fetch_bilinear_no_repeat_8888,
    1397             :       _pixman_image_get_scanline_generic_float
    1398             :     },
    1399             : 
    1400             :     { PIXMAN_x8r8g8b8,
    1401             :       FAST_BILINEAR_FLAGS,
    1402             :       bits_image_fetch_bilinear_no_repeat_8888,
    1403             :       _pixman_image_get_scanline_generic_float
    1404             :     },
    1405             : 
    1406             : #define GENERAL_BILINEAR_FLAGS                                          \
    1407             :     (FAST_PATH_NO_ALPHA_MAP             |                               \
    1408             :      FAST_PATH_NO_ACCESSORS             |                               \
    1409             :      FAST_PATH_HAS_TRANSFORM            |                               \
    1410             :      FAST_PATH_AFFINE_TRANSFORM         |                               \
    1411             :      FAST_PATH_BILINEAR_FILTER)
    1412             : 
    1413             : #define GENERAL_NEAREST_FLAGS                                           \
    1414             :     (FAST_PATH_NO_ALPHA_MAP             |                               \
    1415             :      FAST_PATH_NO_ACCESSORS             |                               \
    1416             :      FAST_PATH_HAS_TRANSFORM            |                               \
    1417             :      FAST_PATH_AFFINE_TRANSFORM         |                               \
    1418             :      FAST_PATH_NEAREST_FILTER)
    1419             : 
    1420             : #define GENERAL_SEPARABLE_CONVOLUTION_FLAGS                             \
    1421             :     (FAST_PATH_NO_ALPHA_MAP            |                                \
    1422             :      FAST_PATH_NO_ACCESSORS            |                                \
    1423             :      FAST_PATH_HAS_TRANSFORM           |                                \
    1424             :      FAST_PATH_AFFINE_TRANSFORM        |                                \
    1425             :      FAST_PATH_SEPARABLE_CONVOLUTION_FILTER)
    1426             :     
    1427             : #define SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat)   \
    1428             :     { PIXMAN_ ## format,                                               \
    1429             :       GENERAL_SEPARABLE_CONVOLUTION_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
    1430             :       bits_image_fetch_separable_convolution_affine_ ## name,          \
    1431             :       _pixman_image_get_scanline_generic_float                         \
    1432             :     },
    1433             : 
    1434             : #define BILINEAR_AFFINE_FAST_PATH(name, format, repeat)                 \
    1435             :     { PIXMAN_ ## format,                                                \
    1436             :       GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT,         \
    1437             :       bits_image_fetch_bilinear_affine_ ## name,                        \
    1438             :       _pixman_image_get_scanline_generic_float                          \
    1439             :     },
    1440             : 
    1441             : #define NEAREST_AFFINE_FAST_PATH(name, format, repeat)                  \
    1442             :     { PIXMAN_ ## format,                                                \
    1443             :       GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT,          \
    1444             :       bits_image_fetch_nearest_affine_ ## name,                         \
    1445             :       _pixman_image_get_scanline_generic_float                          \
    1446             :     },
    1447             : 
    1448             : #define AFFINE_FAST_PATHS(name, format, repeat)                         \
    1449             :     SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat)        \
    1450             :     BILINEAR_AFFINE_FAST_PATH(name, format, repeat)                     \
    1451             :     NEAREST_AFFINE_FAST_PATH(name, format, repeat)
    1452             :     
    1453             :     AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD)
    1454             :     AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE)
    1455             :     AFFINE_FAST_PATHS (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
    1456             :     AFFINE_FAST_PATHS (normal_a8r8g8b8, a8r8g8b8, NORMAL)
    1457             :     AFFINE_FAST_PATHS (pad_x8r8g8b8, x8r8g8b8, PAD)
    1458             :     AFFINE_FAST_PATHS (none_x8r8g8b8, x8r8g8b8, NONE)
    1459             :     AFFINE_FAST_PATHS (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
    1460             :     AFFINE_FAST_PATHS (normal_x8r8g8b8, x8r8g8b8, NORMAL)
    1461             :     AFFINE_FAST_PATHS (pad_a8, a8, PAD)
    1462             :     AFFINE_FAST_PATHS (none_a8, a8, NONE)
    1463             :     AFFINE_FAST_PATHS (reflect_a8, a8, REFLECT)
    1464             :     AFFINE_FAST_PATHS (normal_a8, a8, NORMAL)
    1465             :     AFFINE_FAST_PATHS (pad_r5g6b5, r5g6b5, PAD)
    1466             :     AFFINE_FAST_PATHS (none_r5g6b5, r5g6b5, NONE)
    1467             :     AFFINE_FAST_PATHS (reflect_r5g6b5, r5g6b5, REFLECT)
    1468             :     AFFINE_FAST_PATHS (normal_r5g6b5, r5g6b5, NORMAL)
    1469             : 
    1470             :     /* Affine, no alpha */
    1471             :     { PIXMAN_any,
    1472             :       (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM),
    1473             :       bits_image_fetch_affine_no_alpha,
    1474             :       _pixman_image_get_scanline_generic_float
    1475             :     },
    1476             : 
    1477             :     /* General */
    1478             :     { PIXMAN_any,
    1479             :       0,
    1480             :       bits_image_fetch_general,
    1481             :       _pixman_image_get_scanline_generic_float
    1482             :     },
    1483             : 
    1484             :     { PIXMAN_null },
    1485             : };
    1486             : 
    1487             : static void
    1488          44 : bits_image_property_changed (pixman_image_t *image)
    1489             : {
    1490          44 :     _pixman_bits_image_setup_accessors (&image->bits);
    1491          44 : }
    1492             : 
    1493             : void
    1494           0 : _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter)
    1495             : {
    1496           0 :     pixman_format_code_t format = image->common.extended_format_code;
    1497           0 :     uint32_t flags = image->common.flags;
    1498             :     const fetcher_info_t *info;
    1499             : 
    1500           0 :     for (info = fetcher_info; info->format != PIXMAN_null; ++info)
    1501             :     {
    1502           0 :         if ((info->format == format || info->format == PIXMAN_any)        &&
    1503           0 :             (info->flags & flags) == info->flags)
    1504             :         {
    1505           0 :             if (iter->iter_flags & ITER_NARROW)
    1506             :             {
    1507           0 :                 iter->get_scanline = info->get_scanline_32;
    1508             :             }
    1509             :             else
    1510             :             {
    1511           0 :                 iter->data = info->get_scanline_32;
    1512           0 :                 iter->get_scanline = info->get_scanline_float;
    1513             :             }
    1514           0 :             return;
    1515             :         }
    1516             :     }
    1517             : 
    1518             :     /* Just in case we somehow didn't find a scanline function */
    1519           0 :     iter->get_scanline = _pixman_iter_get_scanline_noop;
    1520             : }
    1521             : 
    1522             : static uint32_t *
    1523           0 : dest_get_scanline_16 (pixman_iter_t *iter, const uint32_t *mask)
    1524             : {
    1525           0 :     pixman_image_t *image  = iter->image;
    1526           0 :     int             x      = iter->x;
    1527           0 :     int             y      = iter->y;
    1528           0 :     int             width  = iter->width;
    1529           0 :     uint32_t *      buffer = iter->buffer;
    1530             : 
    1531           0 :     image->bits.fetch_scanline_16 (image, x, y, width, buffer, mask);
    1532             : 
    1533           0 :     return iter->buffer;
    1534             : }
    1535             : 
    1536             : static uint32_t *
    1537           0 : dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
    1538             : {
    1539           0 :     pixman_image_t *image  = iter->image;
    1540           0 :     int             x      = iter->x;
    1541           0 :     int             y      = iter->y;
    1542           0 :     int             width  = iter->width;
    1543           0 :     uint32_t *      buffer = iter->buffer;
    1544             : 
    1545           0 :     image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
    1546           0 :     if (image->common.alpha_map)
    1547             :     {
    1548             :         uint32_t *alpha;
    1549             : 
    1550           0 :         if ((alpha = malloc (width * sizeof (uint32_t))))
    1551             :         {
    1552             :             int i;
    1553             : 
    1554           0 :             x -= image->common.alpha_origin_x;
    1555           0 :             y -= image->common.alpha_origin_y;
    1556             : 
    1557           0 :             image->common.alpha_map->fetch_scanline_32 (
    1558           0 :                 (pixman_image_t *)image->common.alpha_map,
    1559             :                 x, y, width, alpha, mask);
    1560             : 
    1561           0 :             for (i = 0; i < width; ++i)
    1562             :             {
    1563           0 :                 buffer[i] &= ~0xff000000;
    1564           0 :                 buffer[i] |= (alpha[i] & 0xff000000);
    1565             :             }
    1566             : 
    1567           0 :             free (alpha);
    1568             :         }
    1569             :     }
    1570             : 
    1571           0 :     return iter->buffer;
    1572             : }
    1573             : 
    1574             : static uint32_t *
    1575           0 : dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
    1576             : {
    1577           0 :     bits_image_t *  image  = &iter->image->bits;
    1578           0 :     int             x      = iter->x;
    1579           0 :     int             y      = iter->y;
    1580           0 :     int             width  = iter->width;
    1581           0 :     argb_t *        buffer = (argb_t *)iter->buffer;
    1582             : 
    1583           0 :     image->fetch_scanline_float (
    1584             :         (pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask);
    1585           0 :     if (image->common.alpha_map)
    1586             :     {
    1587             :         argb_t *alpha;
    1588             : 
    1589           0 :         if ((alpha = malloc (width * sizeof (argb_t))))
    1590             :         {
    1591             :             int i;
    1592             : 
    1593           0 :             x -= image->common.alpha_origin_x;
    1594           0 :             y -= image->common.alpha_origin_y;
    1595             : 
    1596           0 :             image->common.alpha_map->fetch_scanline_float (
    1597           0 :                 (pixman_image_t *)image->common.alpha_map,
    1598             :                 x, y, width, (uint32_t *)alpha, mask);
    1599             : 
    1600           0 :             for (i = 0; i < width; ++i)
    1601           0 :                 buffer[i].a = alpha[i].a;
    1602             : 
    1603           0 :             free (alpha);
    1604             :         }
    1605             :     }
    1606             : 
    1607           0 :     return iter->buffer;
    1608             : }
    1609             : 
    1610             : static void
    1611           0 : dest_write_back_16 (pixman_iter_t *iter)
    1612             : {
    1613           0 :     bits_image_t *  image  = &iter->image->bits;
    1614           0 :     int             x      = iter->x;
    1615           0 :     int             y      = iter->y;
    1616           0 :     int             width  = iter->width;
    1617           0 :     const uint32_t *buffer = iter->buffer;
    1618             : 
    1619           0 :     image->store_scanline_16 (image, x, y, width, buffer);
    1620             : 
    1621           0 :     iter->y++;
    1622           0 : }
    1623             : 
    1624             : static void
    1625           0 : dest_write_back_narrow (pixman_iter_t *iter)
    1626             : {
    1627           0 :     bits_image_t *  image  = &iter->image->bits;
    1628           0 :     int             x      = iter->x;
    1629           0 :     int             y      = iter->y;
    1630           0 :     int             width  = iter->width;
    1631           0 :     const uint32_t *buffer = iter->buffer;
    1632             : 
    1633           0 :     image->store_scanline_32 (image, x, y, width, buffer);
    1634             : 
    1635           0 :     if (image->common.alpha_map)
    1636             :     {
    1637           0 :         x -= image->common.alpha_origin_x;
    1638           0 :         y -= image->common.alpha_origin_y;
    1639             : 
    1640           0 :         image->common.alpha_map->store_scanline_32 (
    1641             :             image->common.alpha_map, x, y, width, buffer);
    1642             :     }
    1643             : 
    1644           0 :     iter->y++;
    1645           0 : }
    1646             : 
    1647             : static void
    1648           0 : dest_write_back_wide (pixman_iter_t *iter)
    1649             : {
    1650           0 :     bits_image_t *  image  = &iter->image->bits;
    1651           0 :     int             x      = iter->x;
    1652           0 :     int             y      = iter->y;
    1653           0 :     int             width  = iter->width;
    1654           0 :     const uint32_t *buffer = iter->buffer;
    1655             : 
    1656           0 :     image->store_scanline_float (image, x, y, width, buffer);
    1657             : 
    1658           0 :     if (image->common.alpha_map)
    1659             :     {
    1660           0 :         x -= image->common.alpha_origin_x;
    1661           0 :         y -= image->common.alpha_origin_y;
    1662             : 
    1663           0 :         image->common.alpha_map->store_scanline_float (
    1664             :             image->common.alpha_map, x, y, width, buffer);
    1665             :     }
    1666             : 
    1667           0 :     iter->y++;
    1668           0 : }
    1669             : 
    1670             : void
    1671           0 : _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter)
    1672             : {
    1673           0 :     if (iter->iter_flags & ITER_16)
    1674             :     {
    1675           0 :         if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
    1676             :             (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
    1677             :         {
    1678           0 :             iter->get_scanline = _pixman_iter_get_scanline_noop;
    1679             :         }
    1680             :         else
    1681             :         {
    1682           0 :             iter->get_scanline = dest_get_scanline_16;
    1683             :         }
    1684           0 :         iter->write_back = dest_write_back_16;
    1685             :     }
    1686           0 :     else if (iter->iter_flags & ITER_NARROW)
    1687             :     {
    1688           0 :         if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
    1689             :             (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
    1690             :         {
    1691           0 :             iter->get_scanline = _pixman_iter_get_scanline_noop;
    1692             :         }
    1693             :         else
    1694             :         {
    1695           0 :             iter->get_scanline = dest_get_scanline_narrow;
    1696             :         }
    1697             : 
    1698           0 :         iter->write_back = dest_write_back_narrow;
    1699             :     }
    1700             :     else
    1701             :     {
    1702           0 :         iter->get_scanline = dest_get_scanline_wide;
    1703           0 :         iter->write_back = dest_write_back_wide;
    1704             :     }
    1705           0 : }
    1706             : 
    1707             : static uint32_t *
    1708           0 : create_bits (pixman_format_code_t format,
    1709             :              int                  width,
    1710             :              int                  height,
    1711             :              int *                rowstride_bytes,
    1712             :              pixman_bool_t        clear)
    1713             : {
    1714             :     int stride;
    1715             :     size_t buf_size;
    1716             :     int bpp;
    1717             : 
    1718             :     /* what follows is a long-winded way, avoiding any possibility of integer
    1719             :      * overflows, of saying:
    1720             :      * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t);
    1721             :      */
    1722             : 
    1723           0 :     bpp = PIXMAN_FORMAT_BPP (format);
    1724           0 :     if (_pixman_multiply_overflows_int (width, bpp))
    1725           0 :         return NULL;
    1726             : 
    1727           0 :     stride = width * bpp;
    1728           0 :     if (_pixman_addition_overflows_int (stride, 0x1f))
    1729           0 :         return NULL;
    1730             : 
    1731           0 :     stride += 0x1f;
    1732           0 :     stride >>= 5;
    1733             : 
    1734           0 :     stride *= sizeof (uint32_t);
    1735             : 
    1736           0 :     if (_pixman_multiply_overflows_size (height, stride))
    1737           0 :         return NULL;
    1738             : 
    1739           0 :     buf_size = (size_t)height * stride;
    1740             : 
    1741           0 :     if (rowstride_bytes)
    1742           0 :         *rowstride_bytes = stride;
    1743             : 
    1744           0 :     if (clear)
    1745           0 :         return calloc (buf_size, 1);
    1746             :     else
    1747           0 :         return malloc (buf_size);
    1748             : }
    1749             : 
    1750             : pixman_bool_t
    1751          47 : _pixman_bits_image_init (pixman_image_t *     image,
    1752             :                          pixman_format_code_t format,
    1753             :                          int                  width,
    1754             :                          int                  height,
    1755             :                          uint32_t *           bits,
    1756             :                          int                  rowstride,
    1757             :                          pixman_bool_t        clear)
    1758             : {
    1759          47 :     uint32_t *free_me = NULL;
    1760             : 
    1761          47 :     if (!bits && width && height)
    1762             :     {
    1763             :         int rowstride_bytes;
    1764             : 
    1765           0 :         free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear);
    1766             : 
    1767           0 :         if (!bits)
    1768           0 :             return FALSE;
    1769             : 
    1770           0 :         rowstride = rowstride_bytes / (int) sizeof (uint32_t);
    1771             :     }
    1772             : 
    1773          47 :     _pixman_image_init (image);
    1774             : 
    1775          47 :     image->type = BITS;
    1776          47 :     image->bits.format = format;
    1777          47 :     image->bits.width = width;
    1778          47 :     image->bits.height = height;
    1779          47 :     image->bits.bits = bits;
    1780          47 :     image->bits.free_me = free_me;
    1781          47 :     image->bits.read_func = NULL;
    1782          47 :     image->bits.write_func = NULL;
    1783          47 :     image->bits.rowstride = rowstride;
    1784          47 :     image->bits.indexed = NULL;
    1785             : 
    1786          47 :     image->common.property_changed = bits_image_property_changed;
    1787             : 
    1788          47 :     _pixman_image_reset_clip_region (image);
    1789             : 
    1790          47 :     return TRUE;
    1791             : }
    1792             : 
    1793             : static pixman_image_t *
    1794          47 : create_bits_image_internal (pixman_format_code_t format,
    1795             :                             int                  width,
    1796             :                             int                  height,
    1797             :                             uint32_t *           bits,
    1798             :                             int                  rowstride_bytes,
    1799             :                             pixman_bool_t        clear)
    1800             : {
    1801             :     pixman_image_t *image;
    1802             : 
    1803             :     /* must be a whole number of uint32_t's
    1804             :      */
    1805          47 :     return_val_if_fail (
    1806             :         bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
    1807             : 
    1808          47 :     return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
    1809             : 
    1810          47 :     image = _pixman_image_allocate ();
    1811             : 
    1812          47 :     if (!image)
    1813           0 :         return NULL;
    1814             : 
    1815          47 :     if (!_pixman_bits_image_init (image, format, width, height, bits,
    1816             :                                   rowstride_bytes / (int) sizeof (uint32_t),
    1817             :                                   clear))
    1818             :     {
    1819           0 :         free (image);
    1820           0 :         return NULL;
    1821             :     }
    1822             : 
    1823          47 :     return image;
    1824             : }
    1825             : 
    1826             : /* If bits is NULL, a buffer will be allocated and initialized to 0 */
    1827             : PIXMAN_EXPORT pixman_image_t *
    1828          47 : pixman_image_create_bits (pixman_format_code_t format,
    1829             :                           int                  width,
    1830             :                           int                  height,
    1831             :                           uint32_t *           bits,
    1832             :                           int                  rowstride_bytes)
    1833             : {
    1834          47 :     return create_bits_image_internal (
    1835             :         format, width, height, bits, rowstride_bytes, TRUE);
    1836             : }
    1837             : 
    1838             : 
    1839             : /* If bits is NULL, a buffer will be allocated and _not_ initialized */
    1840             : PIXMAN_EXPORT pixman_image_t *
    1841           0 : pixman_image_create_bits_no_clear (pixman_format_code_t format,
    1842             :                                    int                  width,
    1843             :                                    int                  height,
    1844             :                                    uint32_t *           bits,
    1845             :                                    int                  rowstride_bytes)
    1846             : {
    1847           0 :     return create_bits_image_internal (
    1848             :         format, width, height, bits, rowstride_bytes, FALSE);
    1849             : }

Generated by: LCOV version 1.13