gfx/cairo/libpixman/src/pixman-bits-image.c

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

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

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

     1 /*
     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  */
    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"
    39 static uint32_t *
    40 _pixman_image_get_scanline_generic_float (pixman_iter_t * iter,
    41 					  const uint32_t *mask)
    42 {
    43     pixman_iter_get_scanline_t fetch_32 = iter->data;
    44     uint32_t *buffer = iter->buffer;
    46     fetch_32 (iter, NULL);
    48     pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
    50     return iter->buffer;
    51 }
    53 /* Fetch functions */
    55 static force_inline uint32_t
    56 fetch_pixel_no_alpha (bits_image_t *image,
    57 		      int x, int y, pixman_bool_t check_bounds)
    58 {
    59     if (check_bounds &&
    60 	(x < 0 || x >= image->width || y < 0 || y >= image->height))
    61     {
    62 	return 0;
    63     }
    65     return image->fetch_pixel_32 (image, x, y);
    66 }
    68 typedef uint32_t (* get_pixel_t) (bits_image_t *image,
    69 				  int x, int y, pixman_bool_t check_bounds);
    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     int x0 = pixman_fixed_to_int (x - pixman_fixed_e);
    78     int y0 = pixman_fixed_to_int (y - pixman_fixed_e);
    80     if (image->common.repeat != PIXMAN_REPEAT_NONE)
    81     {
    82 	repeat (image->common.repeat, &x0, image->width);
    83 	repeat (image->common.repeat, &y0, image->height);
    85 	return get_pixel (image, x0, y0, FALSE);
    86     }
    87     else
    88     {
    89 	return get_pixel (image, x0, y0, TRUE);
    90     }
    91 }
    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     pixman_repeat_t repeat_mode = image->common.repeat;
   100     int width = image->width;
   101     int height = image->height;
   102     int x1, y1, x2, y2;
   103     uint32_t tl, tr, bl, br;
   104     int32_t distx, disty;
   106     x1 = x - pixman_fixed_1 / 2;
   107     y1 = y - pixman_fixed_1 / 2;
   109     distx = pixman_fixed_to_bilinear_weight (x1);
   110     disty = pixman_fixed_to_bilinear_weight (y1);
   112     x1 = pixman_fixed_to_int (x1);
   113     y1 = pixman_fixed_to_int (y1);
   114     x2 = x1 + 1;
   115     y2 = y1 + 1;
   117     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);
   124 	tl = get_pixel (image, x1, y1, FALSE);
   125 	bl = get_pixel (image, x1, y2, FALSE);
   126 	tr = get_pixel (image, x2, y1, FALSE);
   127 	br = get_pixel (image, x2, y2, FALSE);
   128     }
   129     else
   130     {
   131 	tl = get_pixel (image, x1, y1, TRUE);
   132 	tr = get_pixel (image, x2, y1, TRUE);
   133 	bl = get_pixel (image, x1, y2, TRUE);
   134 	br = get_pixel (image, x2, y2, TRUE);
   135     }
   137     return bilinear_interpolation (tl, tr, bl, br, distx, disty);
   138 }
   140 static uint32_t *
   141 bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter,
   142 					  const uint32_t *mask)
   143 {
   145     pixman_image_t * ima = iter->image;
   146     int              offset = iter->x;
   147     int              line = iter->y++;
   148     int              width = iter->width;
   149     uint32_t *       buffer = iter->buffer;
   151     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     uint32_t zero[2] = { 0, 0 };
   160     uint32_t one = 1;
   161     int y, y1, y2;
   162     int disty;
   163     int mask_inc;
   164     int w;
   166     /* reference point is the center of the pixel */
   167     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
   168     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
   169     v.vector[2] = pixman_fixed_1;
   171     if (!pixman_transform_point_3d (bits->common.transform, &v))
   172 	return iter->buffer;
   174     ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
   175     x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
   177     y = v.vector[1] - pixman_fixed_1/2;
   178     disty = pixman_fixed_to_bilinear_weight (y);
   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     y1 = pixman_fixed_to_int (y);
   192     y2 = y1 + 1;
   194     if (y1 < 0 || y1 >= bits->height)
   195     {
   196 	top_row = zero;
   197 	x_top = 0;
   198 	ux_top = 0;
   199     }
   200     else
   201     {
   202 	top_row = bits->bits + y1 * bits->rowstride;
   203 	x_top = x;
   204 	ux_top = ux;
   205     }
   207     if (y2 < 0 || y2 >= bits->height)
   208     {
   209 	bottom_row = zero;
   210 	x_bottom = 0;
   211 	ux_bottom = 0;
   212     }
   213     else
   214     {
   215 	bottom_row = bits->bits + y2 * bits->rowstride;
   216 	x_bottom = x;
   217 	ux_bottom = ux;
   218     }
   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     if (!mask)
   225     {
   226         mask_inc = 0;
   227         mask = &one;
   228     }
   229     else
   230     {
   231         /* If have a mask, prepare the variables to check it */
   232         mask_inc = 1;
   233     }
   235     /* If both are zero, then the whole thing is zero */
   236     if (top_row == zero && bottom_row == zero)
   237     {
   238 	memset (buffer, 0, width * sizeof (uint32_t));
   239 	return iter->buffer;
   240     }
   241     else if (bits->format == PIXMAN_x8r8g8b8)
   242     {
   243 	if (top_row == zero)
   244 	{
   245 	    top_mask = 0;
   246 	    bottom_mask = 0xff000000;
   247 	}
   248 	else if (bottom_row == zero)
   249 	{
   250 	    top_mask = 0xff000000;
   251 	    bottom_mask = 0;
   252 	}
   253 	else
   254 	{
   255 	    top_mask = 0xff000000;
   256 	    bottom_mask = 0xff000000;
   257 	}
   258     }
   259     else
   260     {
   261 	top_mask = 0;
   262 	bottom_mask = 0;
   263     }
   265     end = buffer + width;
   267     /* Zero fill to the left of the image */
   268     while (buffer < end && x < pixman_fixed_minus_1)
   269     {
   270 	*buffer++ = 0;
   271 	x += ux;
   272 	x_top += ux_top;
   273 	x_bottom += ux_bottom;
   274 	mask += mask_inc;
   275     }
   277     /* Left edge
   278      */
   279     while (buffer < end && x < 0)
   280     {
   281 	uint32_t tr, br;
   282 	int32_t distx;
   284 	tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
   285 	br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
   287 	distx = pixman_fixed_to_bilinear_weight (x);
   289 	*buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
   291 	x += ux;
   292 	x_top += ux_top;
   293 	x_bottom += ux_bottom;
   294 	mask += mask_inc;
   295     }
   297     /* Main part */
   298     w = pixman_int_to_fixed (bits->width - 1);
   300     while (buffer < end  &&  x < w)
   301     {
   302 	if (*mask)
   303 	{
   304 	    uint32_t tl, tr, bl, br;
   305 	    int32_t distx;
   307 	    tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
   308 	    tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask;
   309 	    bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
   310 	    br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
   312 	    distx = pixman_fixed_to_bilinear_weight (x);
   314 	    *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
   315 	}
   317 	buffer++;
   318 	x += ux;
   319 	x_top += ux_top;
   320 	x_bottom += ux_bottom;
   321 	mask += mask_inc;
   322     }
   324     /* Right Edge */
   325     w = pixman_int_to_fixed (bits->width);
   326     while (buffer < end  &&  x < w)
   327     {
   328 	if (*mask)
   329 	{
   330 	    uint32_t tl, bl;
   331 	    int32_t distx;
   333 	    tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
   334 	    bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
   336 	    distx = pixman_fixed_to_bilinear_weight (x);
   338 	    *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
   339 	}
   341 	buffer++;
   342 	x += ux;
   343 	x_top += ux_top;
   344 	x_bottom += ux_bottom;
   345 	mask += mask_inc;
   346     }
   348     /* Zero fill to the left of the image */
   349     while (buffer < end)
   350 	*buffer++ = 0;
   352     return iter->buffer;
   353 }
   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     pixman_fixed_t *params = image->common.filter_params;
   362     int x_off = (params[0] - pixman_fixed_1) >> 1;
   363     int y_off = (params[1] - pixman_fixed_1) >> 1;
   364     int32_t cwidth = pixman_fixed_to_int (params[0]);
   365     int32_t cheight = pixman_fixed_to_int (params[1]);
   366     int32_t i, j, x1, x2, y1, y2;
   367     pixman_repeat_t repeat_mode = image->common.repeat;
   368     int width = image->width;
   369     int height = image->height;
   370     int srtot, sgtot, sbtot, satot;
   372     params += 2;
   374     x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
   375     y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
   376     x2 = x1 + cwidth;
   377     y2 = y1 + cheight;
   379     srtot = sgtot = sbtot = satot = 0;
   381     for (i = y1; i < y2; ++i)
   382     {
   383 	for (j = x1; j < x2; ++j)
   384 	{
   385 	    int rx = j;
   386 	    int ry = i;
   388 	    pixman_fixed_t f = *params;
   390 	    if (f)
   391 	    {
   392 		uint32_t pixel;
   394 		if (repeat_mode != PIXMAN_REPEAT_NONE)
   395 		{
   396 		    repeat (repeat_mode, &rx, width);
   397 		    repeat (repeat_mode, &ry, height);
   399 		    pixel = get_pixel (image, rx, ry, FALSE);
   400 		}
   401 		else
   402 		{
   403 		    pixel = get_pixel (image, rx, ry, TRUE);
   404 		}
   406 		srtot += (int)RED_8 (pixel) * f;
   407 		sgtot += (int)GREEN_8 (pixel) * f;
   408 		sbtot += (int)BLUE_8 (pixel) * f;
   409 		satot += (int)ALPHA_8 (pixel) * f;
   410 	    }
   412 	    params++;
   413 	}
   414     }
   416     satot = (satot + 0x8000) >> 16;
   417     srtot = (srtot + 0x8000) >> 16;
   418     sgtot = (sgtot + 0x8000) >> 16;
   419     sbtot = (sbtot + 0x8000) >> 16;
   421     satot = CLIP (satot, 0, 0xff);
   422     srtot = CLIP (srtot, 0, 0xff);
   423     sgtot = CLIP (sgtot, 0, 0xff);
   424     sbtot = CLIP (sbtot, 0, 0xff);
   426     return ((satot << 24) | (srtot << 16) | (sgtot <<  8) | (sbtot));
   427 }
   429 static uint32_t
   430 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     pixman_fixed_t *params = image->common.filter_params;
   436     pixman_repeat_t repeat_mode = image->common.repeat;
   437     int width = image->width;
   438     int height = image->height;
   439     int cwidth = pixman_fixed_to_int (params[0]);
   440     int cheight = pixman_fixed_to_int (params[1]);
   441     int x_phase_bits = pixman_fixed_to_int (params[2]);
   442     int y_phase_bits = pixman_fixed_to_int (params[3]);
   443     int x_phase_shift = 16 - x_phase_bits;
   444     int y_phase_shift = 16 - y_phase_bits;
   445     int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
   446     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;
   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     x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
   459     y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
   461     px = (x & 0xffff) >> x_phase_shift;
   462     py = (y & 0xffff) >> y_phase_shift;
   464     y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
   466     x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
   467     y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
   468     x2 = x1 + cwidth;
   469     y2 = y1 + cheight;
   471     srtot = sgtot = sbtot = satot = 0;
   473     for (i = y1; i < y2; ++i)
   474     {
   475         pixman_fixed_48_16_t fy = *y_params++;
   476         pixman_fixed_t *x_params = params + 4 + px * cwidth;
   478         if (fy)
   479         {
   480             for (j = x1; j < x2; ++j)
   481             {
   482                 pixman_fixed_t fx = *x_params++;
   483 		int rx = j;
   484 		int ry = i;
   486                 if (fx)
   487                 {
   488                     pixman_fixed_t f;
   489                     uint32_t pixel;
   491                     if (repeat_mode != PIXMAN_REPEAT_NONE)
   492                     {
   493                         repeat (repeat_mode, &rx, width);
   494                         repeat (repeat_mode, &ry, height);
   496                         pixel = get_pixel (image, rx, ry, FALSE);
   497                     }
   498                     else
   499                     {
   500                         pixel = get_pixel (image, rx, ry, TRUE);
   501 		    }
   503                     f = (fy * fx + 0x8000) >> 16;
   505                     srtot += (int)RED_8 (pixel) * f;
   506                     sgtot += (int)GREEN_8 (pixel) * f;
   507                     sbtot += (int)BLUE_8 (pixel) * f;
   508                     satot += (int)ALPHA_8 (pixel) * f;
   509                 }
   510             }
   511 	}
   512     }
   514     satot = (satot + 0x8000) >> 16;
   515     srtot = (srtot + 0x8000) >> 16;
   516     sgtot = (sgtot + 0x8000) >> 16;
   517     sbtot = (sbtot + 0x8000) >> 16;
   519     satot = CLIP (satot, 0, 0xff);
   520     srtot = CLIP (srtot, 0, 0xff);
   521     sgtot = CLIP (sgtot, 0, 0xff);
   522     sbtot = CLIP (sbtot, 0, 0xff);
   524     return ((satot << 24) | (srtot << 16) | (sgtot <<  8) | (sbtot));
   525 }
   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     switch (image->common.filter)
   534     {
   535     case PIXMAN_FILTER_NEAREST:
   536     case PIXMAN_FILTER_FAST:
   537 	return bits_image_fetch_pixel_nearest (image, x, y, get_pixel);
   538 	break;
   540     case PIXMAN_FILTER_BILINEAR:
   541     case PIXMAN_FILTER_GOOD:
   542     case PIXMAN_FILTER_BEST:
   543 	return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
   544 	break;
   546     case PIXMAN_FILTER_CONVOLUTION:
   547 	return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
   548 	break;
   550     case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
   551         return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel);
   552         break;
   554     default:
   555         break;
   556     }
   558     return 0;
   559 }
   561 static uint32_t *
   562 bits_image_fetch_affine_no_alpha (pixman_iter_t *  iter,
   563 				  const uint32_t * mask)
   564 {
   565     pixman_image_t *image  = iter->image;
   566     int             offset = iter->x;
   567     int             line   = iter->y++;
   568     int             width  = iter->width;
   569     uint32_t *      buffer = iter->buffer;
   571     pixman_fixed_t x, y;
   572     pixman_fixed_t ux, uy;
   573     pixman_vector_t v;
   574     int i;
   576     /* reference point is the center of the pixel */
   577     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
   578     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
   579     v.vector[2] = pixman_fixed_1;
   581     if (image->common.transform)
   582     {
   583 	if (!pixman_transform_point_3d (image->common.transform, &v))
   584 	    return iter->buffer;
   586 	ux = image->common.transform->matrix[0][0];
   587 	uy = image->common.transform->matrix[1][0];
   588     }
   589     else
   590     {
   591 	ux = pixman_fixed_1;
   592 	uy = 0;
   593     }
   595     x = v.vector[0];
   596     y = v.vector[1];
   598     for (i = 0; i < width; ++i)
   599     {
   600 	if (!mask || mask[i])
   601 	{
   602 	    buffer[i] = bits_image_fetch_pixel_filtered (
   603 		&image->bits, x, y, fetch_pixel_no_alpha);
   604 	}
   606 	x += ux;
   607 	y += uy;
   608     }
   610     return buffer;
   611 }
   613 /* General fetcher */
   614 static force_inline uint32_t
   615 fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
   616 {
   617     uint32_t pixel;
   619     if (check_bounds &&
   620 	(x < 0 || x >= image->width || y < 0 || y >= image->height))
   621     {
   622 	return 0;
   623     }
   625     pixel = image->fetch_pixel_32 (image, x, y);
   627     if (image->common.alpha_map)
   628     {
   629 	uint32_t pixel_a;
   631 	x -= image->common.alpha_origin_x;
   632 	y -= image->common.alpha_origin_y;
   634 	if (x < 0 || x >= image->common.alpha_map->width ||
   635 	    y < 0 || y >= image->common.alpha_map->height)
   636 	{
   637 	    pixel_a = 0;
   638 	}
   639 	else
   640 	{
   641 	    pixel_a = image->common.alpha_map->fetch_pixel_32 (
   642 		image->common.alpha_map, x, y);
   644 	    pixel_a = ALPHA_8 (pixel_a);
   645 	}
   647 	pixel &= 0x00ffffff;
   648 	pixel |= (pixel_a << 24);
   649     }
   651     return pixel;
   652 }
   654 static uint32_t *
   655 bits_image_fetch_general (pixman_iter_t  *iter,
   656 			  const uint32_t *mask)
   657 {
   658     pixman_image_t *image  = iter->image;
   659     int             offset = iter->x;
   660     int             line   = iter->y++;
   661     int             width  = iter->width;
   662     uint32_t *      buffer = iter->buffer;
   664     pixman_fixed_t x, y, w;
   665     pixman_fixed_t ux, uy, uw;
   666     pixman_vector_t v;
   667     int i;
   669     /* reference point is the center of the pixel */
   670     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
   671     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
   672     v.vector[2] = pixman_fixed_1;
   674     if (image->common.transform)
   675     {
   676 	if (!pixman_transform_point_3d (image->common.transform, &v))
   677 	    return buffer;
   679 	ux = image->common.transform->matrix[0][0];
   680 	uy = image->common.transform->matrix[1][0];
   681 	uw = image->common.transform->matrix[2][0];
   682     }
   683     else
   684     {
   685 	ux = pixman_fixed_1;
   686 	uy = 0;
   687 	uw = 0;
   688     }
   690     x = v.vector[0];
   691     y = v.vector[1];
   692     w = v.vector[2];
   694     for (i = 0; i < width; ++i)
   695     {
   696 	pixman_fixed_t x0, y0;
   698 	if (!mask || mask[i])
   699 	{
   700 	    if (w != 0)
   701 	    {
   702 		x0 = ((pixman_fixed_48_16_t)x << 16) / w;
   703 		y0 = ((pixman_fixed_48_16_t)y << 16) / w;
   704 	    }
   705 	    else
   706 	    {
   707 		x0 = 0;
   708 		y0 = 0;
   709 	    }
   711 	    buffer[i] = bits_image_fetch_pixel_filtered (
   712 		&image->bits, x0, y0, fetch_pixel_general);
   713 	}
   715 	x += ux;
   716 	y += uy;
   717 	w += uw;
   718     }
   720     return buffer;
   721 }
   723 typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
   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,
   733 					       convert_pixel_t	convert_pixel,
   734 					       pixman_format_code_t	format,
   735 					       pixman_repeat_t	repeat_mode)
   736 {
   737     bits_image_t *bits = &image->bits;
   738     pixman_fixed_t *params = image->common.filter_params;
   739     int cwidth = pixman_fixed_to_int (params[0]);
   740     int cheight = pixman_fixed_to_int (params[1]);
   741     int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
   742     int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
   743     int x_phase_bits = pixman_fixed_to_int (params[2]);
   744     int y_phase_bits = pixman_fixed_to_int (params[3]);
   745     int x_phase_shift = 16 - x_phase_bits;
   746     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;
   752     /* reference point is the center of the pixel */
   753     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
   754     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
   755     v.vector[2] = pixman_fixed_1;
   757     if (!pixman_transform_point_3d (image->common.transform, &v))
   758 	return;
   760     ux = image->common.transform->matrix[0][0];
   761     uy = image->common.transform->matrix[1][0];
   763     vx = v.vector[0];
   764     vy = v.vector[1];
   766     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;
   775 	if (mask && !mask[k])
   776 	    goto next;
   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 	x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
   784 	y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
   786 	px = (x & 0xffff) >> x_phase_shift;
   787 	py = (y & 0xffff) >> y_phase_shift;
   789 	x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
   790 	y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
   791 	x2 = x1 + cwidth;
   792 	y2 = y1 + cheight;
   794 	satot = srtot = sgtot = sbtot = 0;
   796 	y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
   798 	for (i = y1; i < y2; ++i)
   799 	{
   800 	    pixman_fixed_t fy = *y_params++;
   802 	    if (fy)
   803 	    {
   804 		pixman_fixed_t *x_params = params + 4 + px * cwidth;
   806 		for (j = x1; j < x2; ++j)
   807 		{
   808 		    pixman_fixed_t fx = *x_params++;
   809 		    int rx = j;
   810 		    int ry = i;
   812 		    if (fx)
   813 		    {
   814 			pixman_fixed_t f;
   815 			uint32_t pixel, mask;
   816 			uint8_t *row;
   818 			mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
   820 			if (repeat_mode != PIXMAN_REPEAT_NONE)
   821 			{
   822 			    repeat (repeat_mode, &rx, bits->width);
   823 			    repeat (repeat_mode, &ry, bits->height);
   825 			    row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
   826 			    pixel = convert_pixel (row, rx) | mask;
   827 			}
   828 			else
   829 			{
   830 			    if (rx < 0 || ry < 0 || rx >= bits->width || ry >= bits->height)
   831 			    {
   832 				pixel = 0;
   833 			    }
   834 			    else
   835 			    {
   836 				row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
   837 				pixel = convert_pixel (row, rx) | mask;
   838 			    }
   839 			}
   841 			f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16;
   842 			srtot += (int)RED_8 (pixel) * f;
   843 			sgtot += (int)GREEN_8 (pixel) * f;
   844 			sbtot += (int)BLUE_8 (pixel) * f;
   845 			satot += (int)ALPHA_8 (pixel) * f;
   846 		    }
   847 		}
   848 	    }
   849 	}
   851 	satot = (satot + 0x8000) >> 16;
   852 	srtot = (srtot + 0x8000) >> 16;
   853 	sgtot = (sgtot + 0x8000) >> 16;
   854 	sbtot = (sbtot + 0x8000) >> 16;
   856 	satot = CLIP (satot, 0, 0xff);
   857 	srtot = CLIP (srtot, 0, 0xff);
   858 	sgtot = CLIP (sgtot, 0, 0xff);
   859 	sbtot = CLIP (sbtot, 0, 0xff);
   861 	buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0);
   863     next:
   864 	vx += ux;
   865 	vy += uy;
   866     }
   867 }
   869 static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
   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,
   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     bits_image_t *bits = &image->bits;
   887     int i;
   889     /* reference point is the center of the pixel */
   890     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
   891     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
   892     v.vector[2] = pixman_fixed_1;
   894     if (!pixman_transform_point_3d (image->common.transform, &v))
   895 	return;
   897     ux = image->common.transform->matrix[0][0];
   898     uy = image->common.transform->matrix[1][0];
   900     x = v.vector[0];
   901     y = v.vector[1];
   903     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 	int width = image->bits.width;
   909 	int height = image->bits.height;
   910 	const uint8_t *row1;
   911 	const uint8_t *row2;
   913 	if (mask && !mask[i])
   914 	    goto next;
   916 	x1 = x - pixman_fixed_1 / 2;
   917 	y1 = y - pixman_fixed_1 / 2;
   919 	distx = pixman_fixed_to_bilinear_weight (x1);
   920 	disty = pixman_fixed_to_bilinear_weight (y1);
   922 	y1 = pixman_fixed_to_int (y1);
   923 	y2 = y1 + 1;
   924 	x1 = pixman_fixed_to_int (x1);
   925 	x2 = x1 + 1;
   927 	if (repeat_mode != PIXMAN_REPEAT_NONE)
   928 	{
   929 	    uint32_t mask;
   931 	    mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
   933 	    repeat (repeat_mode, &x1, width);
   934 	    repeat (repeat_mode, &y1, height);
   935 	    repeat (repeat_mode, &x2, width);
   936 	    repeat (repeat_mode, &y2, height);
   938 	    row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
   939 	    row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
   941 	    tl = convert_pixel (row1, x1) | mask;
   942 	    tr = convert_pixel (row1, x2) | mask;
   943 	    bl = convert_pixel (row2, x1) | mask;
   944 	    br = convert_pixel (row2, x2) | mask;
   945 	}
   946 	else
   947 	{
   948 	    uint32_t mask1, mask2;
   949 	    int bpp;
   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 	    bpp = PIXMAN_FORMAT_BPP (format);
   961 	    if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
   962 	    {
   963 		buffer[i] = 0;
   964 		goto next;
   965 	    }
   967 	    if (y2 == 0)
   968 	    {
   969 		row1 = zero;
   970 		mask1 = 0;
   971 	    }
   972 	    else
   973 	    {
   974 		row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
   975 		row1 += bpp / 8 * x1;
   977 		mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
   978 	    }
   980 	    if (y1 == height - 1)
   981 	    {
   982 		row2 = zero;
   983 		mask2 = 0;
   984 	    }
   985 	    else
   986 	    {
   987 		row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
   988 		row2 += bpp / 8 * x1;
   990 		mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
   991 	    }
   993 	    if (x2 == 0)
   994 	    {
   995 		tl = 0;
   996 		bl = 0;
   997 	    }
   998 	    else
   999 	    {
  1000 		tl = convert_pixel (row1, 0) | mask1;
  1001 		bl = convert_pixel (row2, 0) | mask2;
  1004 	    if (x1 == width - 1)
  1006 		tr = 0;
  1007 		br = 0;
  1009 	    else
  1011 		tr = convert_pixel (row1, 1) | mask1;
  1012 		br = convert_pixel (row2, 1) | mask2;
  1016 	buffer[i] = bilinear_interpolation (
  1017 	    tl, tr, bl, br, distx, disty);
  1019     next:
  1020 	x += ux;
  1021 	y += uy;
  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,
  1033 				 convert_pixel_t	convert_pixel,
  1034 				 pixman_format_code_t	format,
  1035 				 pixman_repeat_t	repeat_mode)
  1037     pixman_fixed_t x, y;
  1038     pixman_fixed_t ux, uy;
  1039     pixman_vector_t v;
  1040     bits_image_t *bits = &image->bits;
  1041     int i;
  1043     /* reference point is the center of the pixel */
  1044     v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
  1045     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
  1046     v.vector[2] = pixman_fixed_1;
  1048     if (!pixman_transform_point_3d (image->common.transform, &v))
  1049 	return;
  1051     ux = image->common.transform->matrix[0][0];
  1052     uy = image->common.transform->matrix[1][0];
  1054     x = v.vector[0];
  1055     y = v.vector[1];
  1057     for (i = 0; i < width; ++i)
  1059 	int width, height, x0, y0;
  1060 	const uint8_t *row;
  1062 	if (mask && !mask[i])
  1063 	    goto next;
  1065 	width = image->bits.width;
  1066 	height = image->bits.height;
  1067 	x0 = pixman_fixed_to_int (x - pixman_fixed_e);
  1068 	y0 = pixman_fixed_to_int (y - pixman_fixed_e);
  1070 	if (repeat_mode == PIXMAN_REPEAT_NONE &&
  1071 	    (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width))
  1073 	    buffer[i] = 0;
  1075 	else
  1077 	    uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
  1079 	    if (repeat_mode != PIXMAN_REPEAT_NONE)
  1081 		repeat (repeat_mode, &x0, width);
  1082 		repeat (repeat_mode, &y0, height);
  1085 	    row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;
  1087 	    buffer[i] = convert_pixel (row, x0) | mask;
  1090     next:
  1091 	x += ux;
  1092 	y += uy;
  1096 static force_inline uint32_t
  1097 convert_a8r8g8b8 (const uint8_t *row, int x)
  1099     return *(((uint32_t *)row) + x);
  1102 static force_inline uint32_t
  1103 convert_x8r8g8b8 (const uint8_t *row, int x)
  1105     return *(((uint32_t *)row) + x);
  1108 static force_inline uint32_t
  1109 convert_a8 (const uint8_t *row, int x)
  1111     return *(row + x) << 24;
  1114 static force_inline uint32_t
  1115 convert_r5g6b5 (const uint8_t *row, int x)
  1117     return convert_0565_to_0888 (*((uint16_t *)row + x));
  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);                                               \
  1134 	return iter->buffer;                                            \
  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;						\
  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;						\
  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)
  1172 MAKE_FETCHERS (pad_a8r8g8b8,     a8r8g8b8, PIXMAN_REPEAT_PAD)
  1173 MAKE_FETCHERS (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE)
  1174 MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT)
  1175 MAKE_FETCHERS (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL)
  1176 MAKE_FETCHERS (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD)
  1177 MAKE_FETCHERS (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE)
  1178 MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT)
  1179 MAKE_FETCHERS (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL)
  1180 MAKE_FETCHERS (pad_a8,           a8,       PIXMAN_REPEAT_PAD)
  1181 MAKE_FETCHERS (none_a8,          a8,       PIXMAN_REPEAT_NONE)
  1182 MAKE_FETCHERS (reflect_a8,	 a8,       PIXMAN_REPEAT_REFLECT)
  1183 MAKE_FETCHERS (normal_a8,	 a8,       PIXMAN_REPEAT_NORMAL)
  1184 MAKE_FETCHERS (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD)
  1185 MAKE_FETCHERS (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE)
  1186 MAKE_FETCHERS (reflect_r5g6b5,   r5g6b5,   PIXMAN_REPEAT_REFLECT)
  1187 MAKE_FETCHERS (normal_r5g6b5,    r5g6b5,   PIXMAN_REPEAT_NORMAL)
  1189 static void
  1190 replicate_pixel_32 (bits_image_t *   bits,
  1191 		    int              x,
  1192 		    int              y,
  1193 		    int              width,
  1194 		    uint32_t *       buffer)
  1196     uint32_t color;
  1197     uint32_t *end;
  1199     color = bits->fetch_pixel_32 (bits, x, y);
  1201     end = buffer + width;
  1202     while (buffer < end)
  1203 	*(buffer++) = color;
  1206 static void
  1207 replicate_pixel_float (bits_image_t *   bits,
  1208 		       int              x,
  1209 		       int              y,
  1210 		       int              width,
  1211 		       uint32_t *       b)
  1213     argb_t color;
  1214     argb_t *buffer = (argb_t *)b;
  1215     argb_t *end;
  1217     color = bits->fetch_pixel_float (bits, x, y);
  1219     end = buffer + width;
  1220     while (buffer < end)
  1221 	*(buffer++) = color;
  1224 static void
  1225 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)
  1232     uint32_t w;
  1234     if (y < 0 || y >= image->height)
  1236 	memset (buffer, 0, width * (wide? sizeof (argb_t) : 4));
  1237 	return;
  1240     if (x < 0)
  1242 	w = MIN (width, -x);
  1244 	memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4));
  1246 	width -= w;
  1247 	buffer += w * (wide? 4 : 1);
  1248 	x += w;
  1251     if (x < image->width)
  1253 	w = MIN (width, image->width - x);
  1255 	if (wide)
  1256 	    image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
  1257 	else
  1258 	    image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
  1260 	width -= w;
  1261 	buffer += w * (wide? 4 : 1);
  1262 	x += w;
  1265     memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4));
  1268 static void
  1269 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)
  1276     uint32_t w;
  1278     while (y < 0)
  1279 	y += image->height;
  1281     while (y >= image->height)
  1282 	y -= image->height;
  1284     if (image->width == 1)
  1286 	if (wide)
  1287 	    replicate_pixel_float (image, 0, y, width, buffer);
  1288 	else
  1289 	    replicate_pixel_32 (image, 0, y, width, buffer);
  1291 	return;
  1294     while (width)
  1296 	while (x < 0)
  1297 	    x += image->width;
  1298 	while (x >= image->width)
  1299 	    x -= image->width;
  1301 	w = MIN (width, image->width - x);
  1303 	if (wide)
  1304 	    image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
  1305 	else
  1306 	    image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
  1308 	buffer += w * (wide? 4 : 1);
  1309 	x += w;
  1310 	width -= w;
  1314 static uint32_t *
  1315 bits_image_fetch_untransformed_32 (pixman_iter_t * iter,
  1316 				   const uint32_t *mask)
  1318     pixman_image_t *image  = iter->image;
  1319     int             x      = iter->x;
  1320     int             y      = iter->y;
  1321     int             width  = iter->width;
  1322     uint32_t *      buffer = iter->buffer;
  1324     if (image->common.repeat == PIXMAN_REPEAT_NONE)
  1326 	bits_image_fetch_untransformed_repeat_none (
  1327 	    &image->bits, FALSE, x, y, width, buffer);
  1329     else
  1331 	bits_image_fetch_untransformed_repeat_normal (
  1332 	    &image->bits, FALSE, x, y, width, buffer);
  1335     iter->y++;
  1336     return buffer;
  1339 static uint32_t *
  1340 bits_image_fetch_untransformed_float (pixman_iter_t * iter,
  1341 				      const uint32_t *mask)
  1343     pixman_image_t *image  = iter->image;
  1344     int             x      = iter->x;
  1345     int             y      = iter->y;
  1346     int             width  = iter->width;
  1347     uint32_t *      buffer = iter->buffer;
  1349     if (image->common.repeat == PIXMAN_REPEAT_NONE)
  1351 	bits_image_fetch_untransformed_repeat_none (
  1352 	    &image->bits, TRUE, x, y, width, buffer);
  1354     else
  1356 	bits_image_fetch_untransformed_repeat_normal (
  1357 	    &image->bits, TRUE, x, y, width, buffer);
  1360     iter->y++;
  1361     return buffer;
  1364 typedef struct
  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;
  1372 static const fetcher_info_t fetcher_info[] =
  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     },
  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)
  1394     { PIXMAN_a8r8g8b8,
  1395       FAST_BILINEAR_FLAGS,
  1396       bits_image_fetch_bilinear_no_repeat_8888,
  1397       _pixman_image_get_scanline_generic_float
  1398     },
  1400     { PIXMAN_x8r8g8b8,
  1401       FAST_BILINEAR_FLAGS,
  1402       bits_image_fetch_bilinear_no_repeat_8888,
  1403       _pixman_image_get_scanline_generic_float
  1404     },
  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)
  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)
  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)
  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     },
  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     },
  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     },
  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)
  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)
  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     },
  1477     /* General */
  1478     { PIXMAN_any,
  1479       0,
  1480       bits_image_fetch_general,
  1481       _pixman_image_get_scanline_generic_float
  1482     },
  1484     { PIXMAN_null },
  1485 };
  1487 static void
  1488 bits_image_property_changed (pixman_image_t *image)
  1490     _pixman_bits_image_setup_accessors (&image->bits);
  1493 void
  1494 _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter)
  1496     pixman_format_code_t format = image->common.extended_format_code;
  1497     uint32_t flags = image->common.flags;
  1498     const fetcher_info_t *info;
  1500     for (info = fetcher_info; info->format != PIXMAN_null; ++info)
  1502 	if ((info->format == format || info->format == PIXMAN_any)	&&
  1503 	    (info->flags & flags) == info->flags)
  1505 	    if (iter->iter_flags & ITER_NARROW)
  1507 		iter->get_scanline = info->get_scanline_32;
  1509 	    else
  1511 		iter->data = info->get_scanline_32;
  1512 		iter->get_scanline = info->get_scanline_float;
  1514 	    return;
  1518     /* Just in case we somehow didn't find a scanline function */
  1519     iter->get_scanline = _pixman_iter_get_scanline_noop;
  1522 static uint32_t *
  1523 dest_get_scanline_16 (pixman_iter_t *iter, const uint32_t *mask)
  1525     pixman_image_t *image  = iter->image;
  1526     int             x      = iter->x;
  1527     int             y      = iter->y;
  1528     int             width  = iter->width;
  1529     uint32_t *	    buffer = iter->buffer;
  1531     image->bits.fetch_scanline_16 (image, x, y, width, buffer, mask);
  1533     return iter->buffer;
  1536 static uint32_t *
  1537 dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
  1539     pixman_image_t *image  = iter->image;
  1540     int             x      = iter->x;
  1541     int             y      = iter->y;
  1542     int             width  = iter->width;
  1543     uint32_t *	    buffer = iter->buffer;
  1545     image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
  1546     if (image->common.alpha_map)
  1548 	uint32_t *alpha;
  1550 	if ((alpha = malloc (width * sizeof (uint32_t))))
  1552 	    int i;
  1554 	    x -= image->common.alpha_origin_x;
  1555 	    y -= image->common.alpha_origin_y;
  1557 	    image->common.alpha_map->fetch_scanline_32 (
  1558 		(pixman_image_t *)image->common.alpha_map,
  1559 		x, y, width, alpha, mask);
  1561 	    for (i = 0; i < width; ++i)
  1563 		buffer[i] &= ~0xff000000;
  1564 		buffer[i] |= (alpha[i] & 0xff000000);
  1567 	    free (alpha);
  1571     return iter->buffer;
  1574 static uint32_t *
  1575 dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
  1577     bits_image_t *  image  = &iter->image->bits;
  1578     int             x      = iter->x;
  1579     int             y      = iter->y;
  1580     int             width  = iter->width;
  1581     argb_t *	    buffer = (argb_t *)iter->buffer;
  1583     image->fetch_scanline_float (
  1584 	(pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask);
  1585     if (image->common.alpha_map)
  1587 	argb_t *alpha;
  1589 	if ((alpha = malloc (width * sizeof (argb_t))))
  1591 	    int i;
  1593 	    x -= image->common.alpha_origin_x;
  1594 	    y -= image->common.alpha_origin_y;
  1596 	    image->common.alpha_map->fetch_scanline_float (
  1597 		(pixman_image_t *)image->common.alpha_map,
  1598 		x, y, width, (uint32_t *)alpha, mask);
  1600 	    for (i = 0; i < width; ++i)
  1601 		buffer[i].a = alpha[i].a;
  1603 	    free (alpha);
  1607     return iter->buffer;
  1610 static void
  1611 dest_write_back_16 (pixman_iter_t *iter)
  1613     bits_image_t *  image  = &iter->image->bits;
  1614     int             x      = iter->x;
  1615     int             y      = iter->y;
  1616     int             width  = iter->width;
  1617     const uint32_t *buffer = iter->buffer;
  1619     image->store_scanline_16 (image, x, y, width, buffer);
  1621     iter->y++;
  1624 static void
  1625 dest_write_back_narrow (pixman_iter_t *iter)
  1627     bits_image_t *  image  = &iter->image->bits;
  1628     int             x      = iter->x;
  1629     int             y      = iter->y;
  1630     int             width  = iter->width;
  1631     const uint32_t *buffer = iter->buffer;
  1633     image->store_scanline_32 (image, x, y, width, buffer);
  1635     if (image->common.alpha_map)
  1637 	x -= image->common.alpha_origin_x;
  1638 	y -= image->common.alpha_origin_y;
  1640 	image->common.alpha_map->store_scanline_32 (
  1641 	    image->common.alpha_map, x, y, width, buffer);
  1644     iter->y++;
  1647 static void
  1648 dest_write_back_wide (pixman_iter_t *iter)
  1650     bits_image_t *  image  = &iter->image->bits;
  1651     int             x      = iter->x;
  1652     int             y      = iter->y;
  1653     int             width  = iter->width;
  1654     const uint32_t *buffer = iter->buffer;
  1656     image->store_scanline_float (image, x, y, width, buffer);
  1658     if (image->common.alpha_map)
  1660 	x -= image->common.alpha_origin_x;
  1661 	y -= image->common.alpha_origin_y;
  1663 	image->common.alpha_map->store_scanline_float (
  1664 	    image->common.alpha_map, x, y, width, buffer);
  1667     iter->y++;
  1670 void
  1671 _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter)
  1673     if (iter->iter_flags & ITER_16)
  1675         if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
  1676 	    (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
  1678             iter->get_scanline = _pixman_iter_get_scanline_noop;
  1680         else
  1682 	    iter->get_scanline = dest_get_scanline_16;
  1684 	iter->write_back = dest_write_back_16;
  1686     else if (iter->iter_flags & ITER_NARROW)
  1688 	if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
  1689 	    (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
  1691 	    iter->get_scanline = _pixman_iter_get_scanline_noop;
  1693 	else
  1695 	    iter->get_scanline = dest_get_scanline_narrow;
  1698 	iter->write_back = dest_write_back_narrow;
  1700     else
  1702 	iter->get_scanline = dest_get_scanline_wide;
  1703 	iter->write_back = dest_write_back_wide;
  1707 static uint32_t *
  1708 create_bits (pixman_format_code_t format,
  1709              int                  width,
  1710              int                  height,
  1711              int *		  rowstride_bytes,
  1712 	     pixman_bool_t	  clear)
  1714     int stride;
  1715     size_t buf_size;
  1716     int bpp;
  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      */
  1723     bpp = PIXMAN_FORMAT_BPP (format);
  1724     if (_pixman_multiply_overflows_int (width, bpp))
  1725 	return NULL;
  1727     stride = width * bpp;
  1728     if (_pixman_addition_overflows_int (stride, 0x1f))
  1729 	return NULL;
  1731     stride += 0x1f;
  1732     stride >>= 5;
  1734     stride *= sizeof (uint32_t);
  1736     if (_pixman_multiply_overflows_size (height, stride))
  1737 	return NULL;
  1739     buf_size = height * stride;
  1741     if (rowstride_bytes)
  1742 	*rowstride_bytes = stride;
  1744     if (clear)
  1745 	return calloc (buf_size, 1);
  1746     else
  1747 	return malloc (buf_size);
  1750 pixman_bool_t
  1751 _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)
  1759     uint32_t *free_me = NULL;
  1761     if (!bits && width && height)
  1763 	int rowstride_bytes;
  1765 	free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear);
  1767 	if (!bits)
  1768 	    return FALSE;
  1770 	rowstride = rowstride_bytes / (int) sizeof (uint32_t);
  1773     _pixman_image_init (image);
  1775     image->type = BITS;
  1776     image->bits.format = format;
  1777     image->bits.width = width;
  1778     image->bits.height = height;
  1779     image->bits.bits = bits;
  1780     image->bits.free_me = free_me;
  1781     image->bits.read_func = NULL;
  1782     image->bits.write_func = NULL;
  1783     image->bits.rowstride = rowstride;
  1784     image->bits.indexed = NULL;
  1786     image->common.property_changed = bits_image_property_changed;
  1788     _pixman_image_reset_clip_region (image);
  1790     return TRUE;
  1793 static pixman_image_t *
  1794 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)
  1801     pixman_image_t *image;
  1803     /* must be a whole number of uint32_t's
  1804      */
  1805     return_val_if_fail (
  1806 	bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
  1808     return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
  1810     image = _pixman_image_allocate ();
  1812     if (!image)
  1813 	return NULL;
  1815     if (!_pixman_bits_image_init (image, format, width, height, bits,
  1816 				  rowstride_bytes / (int) sizeof (uint32_t),
  1817 				  clear))
  1819 	free (image);
  1820 	return NULL;
  1823     return image;
  1826 /* If bits is NULL, a buffer will be allocated and initialized to 0 */
  1827 PIXMAN_EXPORT pixman_image_t *
  1828 pixman_image_create_bits (pixman_format_code_t format,
  1829                           int                  width,
  1830                           int                  height,
  1831                           uint32_t *           bits,
  1832                           int                  rowstride_bytes)
  1834     return create_bits_image_internal (
  1835 	format, width, height, bits, rowstride_bytes, TRUE);
  1839 /* If bits is NULL, a buffer will be allocated and _not_ initialized */
  1840 PIXMAN_EXPORT pixman_image_t *
  1841 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)
  1847     return create_bits_image_internal (
  1848 	format, width, height, bits, rowstride_bytes, FALSE);

mercurial