Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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