Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 3930 → Rev 3931

/programs/develop/libraries/pixman/pixman-bits-image.c
34,45 → 34,21
#include <string.h>
#include "pixman-private.h"
#include "pixman-combine32.h"
#include "pixman-inlines.h"
 
/* Store functions */
void
_pixman_image_store_scanline_32 (bits_image_t * image,
int x,
int y,
int width,
const uint32_t *buffer)
static uint32_t *
_pixman_image_get_scanline_generic_float (pixman_iter_t * iter,
const uint32_t *mask)
{
image->store_scanline_32 (image, x, y, width, buffer);
pixman_iter_get_scanline_t fetch_32 = iter->data;
uint32_t *buffer = iter->buffer;
 
if (image->common.alpha_map)
{
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
fetch_32 (iter, NULL);
 
image->common.alpha_map->store_scanline_32 (
image->common.alpha_map, x, y, width, buffer);
}
}
pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
 
void
_pixman_image_store_scanline_64 (bits_image_t * image,
int x,
int y,
int width,
const uint32_t *buffer)
{
image->store_scanline_64 (image, x, y, width, buffer);
 
if (image->common.alpha_map)
{
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
 
image->common.alpha_map->store_scanline_64 (
image->common.alpha_map, x, y, width, buffer);
return iter->buffer;
}
}
 
/* Fetch functions */
 
92,34 → 68,6
typedef uint32_t (* get_pixel_t) (bits_image_t *image,
int x, int y, pixman_bool_t check_bounds);
 
static force_inline void
repeat (pixman_repeat_t repeat, int size, int *coord)
{
switch (repeat)
{
case PIXMAN_REPEAT_NORMAL:
*coord = MOD (*coord, size);
break;
 
case PIXMAN_REPEAT_PAD:
*coord = CLIP (*coord, 0, size - 1);
break;
 
case PIXMAN_REPEAT_REFLECT:
*coord = MOD (*coord, size * 2);
 
if (*coord >= size)
*coord = size * 2 - *coord - 1;
break;
 
case PIXMAN_REPEAT_NONE:
break;
 
default:
break;
}
}
 
static force_inline uint32_t
bits_image_fetch_pixel_nearest (bits_image_t *image,
pixman_fixed_t x,
131,8 → 79,8
 
if (image->common.repeat != PIXMAN_REPEAT_NONE)
{
repeat (image->common.repeat, image->width, &x0);
repeat (image->common.repeat, image->height, &y0);
repeat (image->common.repeat, &x0, image->width);
repeat (image->common.repeat, &y0, image->height);
 
return get_pixel (image, x0, y0, FALSE);
}
142,98 → 90,7
}
}
 
#if SIZEOF_LONG > 4
 
static force_inline uint32_t
bilinear_interpolation (uint32_t tl, uint32_t tr,
uint32_t bl, uint32_t br,
int distx, int disty)
{
uint64_t distxy, distxiy, distixy, distixiy;
uint64_t tl64, tr64, bl64, br64;
uint64_t f, r;
 
distxy = distx * disty;
distxiy = distx * (256 - disty);
distixy = (256 - distx) * disty;
distixiy = (256 - distx) * (256 - disty);
 
/* Alpha and Blue */
tl64 = tl & 0xff0000ff;
tr64 = tr & 0xff0000ff;
bl64 = bl & 0xff0000ff;
br64 = br & 0xff0000ff;
 
f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
r = f & 0x0000ff0000ff0000ull;
 
/* Red and Green */
tl64 = tl;
tl64 = ((tl64 << 16) & 0x000000ff00000000ull) | (tl64 & 0x0000ff00ull);
 
tr64 = tr;
tr64 = ((tr64 << 16) & 0x000000ff00000000ull) | (tr64 & 0x0000ff00ull);
 
bl64 = bl;
bl64 = ((bl64 << 16) & 0x000000ff00000000ull) | (bl64 & 0x0000ff00ull);
 
br64 = br;
br64 = ((br64 << 16) & 0x000000ff00000000ull) | (br64 & 0x0000ff00ull);
 
f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
r |= ((f >> 16) & 0x000000ff00000000ull) | (f & 0xff000000ull);
 
return (uint32_t)(r >> 16);
}
 
#else
 
static force_inline uint32_t
bilinear_interpolation (uint32_t tl, uint32_t tr,
uint32_t bl, uint32_t br,
int distx, int disty)
{
int distxy, distxiy, distixy, distixiy;
uint32_t f, r;
 
distxy = distx * disty;
distxiy = (distx << 8) - distxy; /* distx * (256 - disty) */
distixy = (disty << 8) - distxy; /* disty * (256 - distx) */
distixiy =
256 * 256 - (disty << 8) -
(distx << 8) + distxy; /* (256 - distx) * (256 - disty) */
 
/* Blue */
r = (tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy
+ (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy;
 
/* Green */
f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy
+ (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy;
r |= f & 0xff000000;
 
tl >>= 16;
tr >>= 16;
bl >>= 16;
br >>= 16;
r >>= 16;
 
/* Red */
f = (tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy
+ (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy;
r |= f & 0x00ff0000;
 
/* Alpha */
f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy
+ (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy;
r |= f & 0xff000000;
 
return r;
}
 
#endif
 
static force_inline uint32_t
bits_image_fetch_pixel_bilinear (bits_image_t *image,
pixman_fixed_t x,
pixman_fixed_t y,
249,8 → 106,8
x1 = x - pixman_fixed_1 / 2;
y1 = y - pixman_fixed_1 / 2;
 
distx = (x1 >> 8) & 0xff;
disty = (y1 >> 8) & 0xff;
distx = pixman_fixed_to_bilinear_weight (x1);
disty = pixman_fixed_to_bilinear_weight (y1);
 
x1 = pixman_fixed_to_int (x1);
y1 = pixman_fixed_to_int (y1);
259,10 → 116,10
 
if (repeat_mode != PIXMAN_REPEAT_NONE)
{
repeat (repeat_mode, width, &x1);
repeat (repeat_mode, height, &y1);
repeat (repeat_mode, width, &x2);
repeat (repeat_mode, height, &y2);
repeat (repeat_mode, &x1, width);
repeat (repeat_mode, &y1, height);
repeat (repeat_mode, &x2, width);
repeat (repeat_mode, &y2, height);
 
tl = get_pixel (image, x1, y1, FALSE);
bl = get_pixel (image, x1, y2, FALSE);
280,14 → 137,17
return bilinear_interpolation (tl, tr, bl, br, distx, disty);
}
 
static void
bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima,
int offset,
int line,
int width,
uint32_t * buffer,
static uint32_t *
bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter,
const uint32_t * mask)
{
 
pixman_image_t * ima = iter->image;
int offset = iter->x;
int line = iter->y++;
int width = iter->width;
uint32_t * buffer = iter->buffer;
 
bits_image_t *bits = &ima->bits;
pixman_fixed_t x_top, x_bottom, x;
pixman_fixed_t ux_top, ux_bottom, ux;
309,13 → 169,13
v.vector[2] = pixman_fixed_1;
 
if (!pixman_transform_point_3d (bits->common.transform, &v))
return;
return iter->buffer;
 
ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
 
y = v.vector[1] - pixman_fixed_1/2;
disty = (y >> 8) & 0xff;
disty = pixman_fixed_to_bilinear_weight (y);
 
/* Load the pointers to the first and second lines from the source
* image that bilinear code must read.
376,7 → 236,7
if (top_row == zero && bottom_row == zero)
{
memset (buffer, 0, width * sizeof (uint32_t));
return;
return iter->buffer;
}
else if (bits->format == PIXMAN_x8r8g8b8)
{
424,7 → 284,7
tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
 
distx = (x >> 8) & 0xff;
distx = pixman_fixed_to_bilinear_weight (x);
 
*buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
 
449,7 → 309,7
bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
 
distx = (x >> 8) & 0xff;
distx = pixman_fixed_to_bilinear_weight (x);
 
*buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
}
473,7 → 333,7
tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
 
distx = (x >> 8) & 0xff;
distx = pixman_fixed_to_bilinear_weight (x);
 
*buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
}
488,6 → 348,8
/* Zero fill to the left of the image */
while (buffer < end)
*buffer++ = 0;
 
return iter->buffer;
}
 
static force_inline uint32_t
501,11 → 363,11
int y_off = (params[1] - pixman_fixed_1) >> 1;
int32_t cwidth = pixman_fixed_to_int (params[0]);
int32_t cheight = pixman_fixed_to_int (params[1]);
int32_t srtot, sgtot, sbtot, satot;
int32_t i, j, x1, x2, y1, y2;
pixman_repeat_t repeat_mode = image->common.repeat;
int width = image->width;
int height = image->height;
int srtot, sgtot, sbtot, satot;
 
params += 2;
 
531,8 → 393,8
 
if (repeat_mode != PIXMAN_REPEAT_NONE)
{
repeat (repeat_mode, width, &rx);
repeat (repeat_mode, height, &ry);
repeat (repeat_mode, &rx, width);
repeat (repeat_mode, &ry, height);
 
pixel = get_pixel (image, rx, ry, FALSE);
}
541,10 → 403,10
pixel = get_pixel (image, rx, ry, TRUE);
}
 
srtot += RED_8 (pixel) * f;
sgtot += GREEN_8 (pixel) * f;
sbtot += BLUE_8 (pixel) * f;
satot += ALPHA_8 (pixel) * f;
srtot += (int)RED_8 (pixel) * f;
sgtot += (int)GREEN_8 (pixel) * f;
sbtot += (int)BLUE_8 (pixel) * f;
satot += (int)ALPHA_8 (pixel) * f;
}
 
params++;
551,10 → 413,10
}
}
 
satot >>= 16;
srtot >>= 16;
sgtot >>= 16;
sbtot >>= 16;
satot = (satot + 0x8000) >> 16;
srtot = (srtot + 0x8000) >> 16;
sgtot = (sgtot + 0x8000) >> 16;
sbtot = (sbtot + 0x8000) >> 16;
 
satot = CLIP (satot, 0, 0xff);
srtot = CLIP (srtot, 0, 0xff);
564,6 → 426,104
return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
}
 
static uint32_t
bits_image_fetch_pixel_separable_convolution (bits_image_t *image,
pixman_fixed_t x,
pixman_fixed_t y,
get_pixel_t get_pixel)
{
pixman_fixed_t *params = image->common.filter_params;
pixman_repeat_t repeat_mode = image->common.repeat;
int width = image->width;
int height = image->height;
int cwidth = pixman_fixed_to_int (params[0]);
int cheight = pixman_fixed_to_int (params[1]);
int x_phase_bits = pixman_fixed_to_int (params[2]);
int y_phase_bits = pixman_fixed_to_int (params[3]);
int x_phase_shift = 16 - x_phase_bits;
int y_phase_shift = 16 - y_phase_bits;
int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
pixman_fixed_t *y_params;
int srtot, sgtot, sbtot, satot;
int32_t x1, x2, y1, y2;
int32_t px, py;
int i, j;
 
/* Round x and y to the middle of the closest phase before continuing. This
* ensures that the convolution matrix is aligned right, since it was
* positioned relative to a particular phase (and not relative to whatever
* exact fraction we happen to get here).
*/
x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
 
px = (x & 0xffff) >> x_phase_shift;
py = (y & 0xffff) >> y_phase_shift;
 
y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
 
x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
x2 = x1 + cwidth;
y2 = y1 + cheight;
 
srtot = sgtot = sbtot = satot = 0;
 
for (i = y1; i < y2; ++i)
{
pixman_fixed_48_16_t fy = *y_params++;
pixman_fixed_t *x_params = params + 4 + px * cwidth;
 
if (fy)
{
for (j = x1; j < x2; ++j)
{
pixman_fixed_t fx = *x_params++;
int rx = j;
int ry = i;
 
if (fx)
{
pixman_fixed_t f;
uint32_t pixel;
 
if (repeat_mode != PIXMAN_REPEAT_NONE)
{
repeat (repeat_mode, &rx, width);
repeat (repeat_mode, &ry, height);
 
pixel = get_pixel (image, rx, ry, FALSE);
}
else
{
pixel = get_pixel (image, rx, ry, TRUE);
}
 
f = (fy * fx + 0x8000) >> 16;
 
srtot += (int)RED_8 (pixel) * f;
sgtot += (int)GREEN_8 (pixel) * f;
sbtot += (int)BLUE_8 (pixel) * f;
satot += (int)ALPHA_8 (pixel) * f;
}
}
}
}
 
satot = (satot + 0x8000) >> 16;
srtot = (srtot + 0x8000) >> 16;
sgtot = (sgtot + 0x8000) >> 16;
sbtot = (sbtot + 0x8000) >> 16;
 
satot = CLIP (satot, 0, 0xff);
srtot = CLIP (srtot, 0, 0xff);
sgtot = CLIP (sgtot, 0, 0xff);
sbtot = CLIP (sbtot, 0, 0xff);
 
return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
}
 
static force_inline uint32_t
bits_image_fetch_pixel_filtered (bits_image_t *image,
pixman_fixed_t x,
587,6 → 547,10
return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
break;
 
case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel);
break;
 
default:
break;
}
594,14 → 558,16
return 0;
}
 
static void
bits_image_fetch_affine_no_alpha (pixman_image_t * image,
int offset,
int line,
int width,
uint32_t * buffer,
static uint32_t *
bits_image_fetch_affine_no_alpha (pixman_iter_t * iter,
const uint32_t * mask)
{
pixman_image_t *image = iter->image;
int offset = iter->x;
int line = iter->y++;
int width = iter->width;
uint32_t * buffer = iter->buffer;
 
pixman_fixed_t x, y;
pixman_fixed_t ux, uy;
pixman_vector_t v;
615,7 → 581,7
if (image->common.transform)
{
if (!pixman_transform_point_3d (image->common.transform, &v))
return;
return iter->buffer;
 
ux = image->common.transform->matrix[0][0];
uy = image->common.transform->matrix[1][0];
640,6 → 606,8
x += ux;
y += uy;
}
 
return buffer;
}
 
/* General fetcher */
683,14 → 651,16
return pixel;
}
 
static void
bits_image_fetch_general (pixman_image_t * image,
int offset,
int line,
int width,
uint32_t * buffer,
static uint32_t *
bits_image_fetch_general (pixman_iter_t *iter,
const uint32_t * mask)
{
pixman_image_t *image = iter->image;
int offset = iter->x;
int line = iter->y++;
int width = iter->width;
uint32_t * buffer = iter->buffer;
 
pixman_fixed_t x, y, w;
pixman_fixed_t ux, uy, uw;
pixman_vector_t v;
704,7 → 674,7
if (image->common.transform)
{
if (!pixman_transform_point_3d (image->common.transform, &v))
return;
return buffer;
 
ux = image->common.transform->matrix[0][0];
uy = image->common.transform->matrix[1][0];
746,13 → 716,159
y += uy;
w += uw;
}
 
return buffer;
}
 
static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
 
static force_inline void
bits_image_fetch_separable_convolution_affine (pixman_image_t * image,
int offset,
int line,
int width,
uint32_t * buffer,
const uint32_t * mask,
 
convert_pixel_t convert_pixel,
pixman_format_code_t format,
pixman_repeat_t repeat_mode)
{
bits_image_t *bits = &image->bits;
pixman_fixed_t *params = image->common.filter_params;
int cwidth = pixman_fixed_to_int (params[0]);
int cheight = pixman_fixed_to_int (params[1]);
int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
int x_phase_bits = pixman_fixed_to_int (params[2]);
int y_phase_bits = pixman_fixed_to_int (params[3]);
int x_phase_shift = 16 - x_phase_bits;
int y_phase_shift = 16 - y_phase_bits;
pixman_fixed_t vx, vy;
pixman_fixed_t ux, uy;
pixman_vector_t v;
int k;
 
/* reference point is the center of the pixel */
v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
v.vector[2] = pixman_fixed_1;
 
if (!pixman_transform_point_3d (image->common.transform, &v))
return;
 
ux = image->common.transform->matrix[0][0];
uy = image->common.transform->matrix[1][0];
 
vx = v.vector[0];
vy = v.vector[1];
 
for (k = 0; k < width; ++k)
{
pixman_fixed_t *y_params;
int satot, srtot, sgtot, sbtot;
pixman_fixed_t x, y;
int32_t x1, x2, y1, y2;
int32_t px, py;
int i, j;
 
if (mask && !mask[k])
goto next;
 
/* Round x and y to the middle of the closest phase before continuing. This
* ensures that the convolution matrix is aligned right, since it was
* positioned relative to a particular phase (and not relative to whatever
* exact fraction we happen to get here).
*/
x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
 
px = (x & 0xffff) >> x_phase_shift;
py = (y & 0xffff) >> y_phase_shift;
 
x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
x2 = x1 + cwidth;
y2 = y1 + cheight;
 
satot = srtot = sgtot = sbtot = 0;
 
y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
 
for (i = y1; i < y2; ++i)
{
pixman_fixed_t fy = *y_params++;
 
if (fy)
{
pixman_fixed_t *x_params = params + 4 + px * cwidth;
 
for (j = x1; j < x2; ++j)
{
pixman_fixed_t fx = *x_params++;
int rx = j;
int ry = i;
if (fx)
{
pixman_fixed_t f;
uint32_t pixel, mask;
uint8_t *row;
 
mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
 
if (repeat_mode != PIXMAN_REPEAT_NONE)
{
repeat (repeat_mode, &rx, bits->width);
repeat (repeat_mode, &ry, bits->height);
 
row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
pixel = convert_pixel (row, rx) | mask;
}
else
{
if (rx < 0 || ry < 0 || rx >= bits->width || ry >= bits->height)
{
pixel = 0;
}
else
{
row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
pixel = convert_pixel (row, rx) | mask;
}
}
 
f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16;
srtot += (int)RED_8 (pixel) * f;
sgtot += (int)GREEN_8 (pixel) * f;
sbtot += (int)BLUE_8 (pixel) * f;
satot += (int)ALPHA_8 (pixel) * f;
}
}
}
}
 
satot = (satot + 0x8000) >> 16;
srtot = (srtot + 0x8000) >> 16;
sgtot = (sgtot + 0x8000) >> 16;
sbtot = (sbtot + 0x8000) >> 16;
 
satot = CLIP (satot, 0, 0xff);
srtot = CLIP (srtot, 0, 0xff);
sgtot = CLIP (sgtot, 0, 0xff);
sbtot = CLIP (sbtot, 0, 0xff);
 
buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0);
 
next:
vx += ux;
vy += uy;
}
}
 
static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
static force_inline void
bits_image_fetch_bilinear_affine (pixman_image_t * image,
int offset,
int line,
800,8 → 916,8
x1 = x - pixman_fixed_1 / 2;
y1 = y - pixman_fixed_1 / 2;
 
distx = (x1 >> 8) & 0xff;
disty = (y1 >> 8) & 0xff;
distx = pixman_fixed_to_bilinear_weight (x1);
disty = pixman_fixed_to_bilinear_weight (y1);
 
y1 = pixman_fixed_to_int (y1);
y2 = y1 + 1;
814,10 → 930,10
 
mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
 
repeat (repeat_mode, width, &x1);
repeat (repeat_mode, height, &y1);
repeat (repeat_mode, width, &x2);
repeat (repeat_mode, height, &y2);
repeat (repeat_mode, &x1, width);
repeat (repeat_mode, &y1, height);
repeat (repeat_mode, &x2, width);
repeat (repeat_mode, &y2, height);
 
row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
906,6 → 1022,77
}
}
 
static force_inline void
bits_image_fetch_nearest_affine (pixman_image_t * image,
int offset,
int line,
int width,
uint32_t * buffer,
const uint32_t * mask,
convert_pixel_t convert_pixel,
pixman_format_code_t format,
pixman_repeat_t repeat_mode)
{
pixman_fixed_t x, y;
pixman_fixed_t ux, uy;
pixman_vector_t v;
bits_image_t *bits = &image->bits;
int i;
 
/* reference point is the center of the pixel */
v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
v.vector[2] = pixman_fixed_1;
 
if (!pixman_transform_point_3d (image->common.transform, &v))
return;
 
ux = image->common.transform->matrix[0][0];
uy = image->common.transform->matrix[1][0];
 
x = v.vector[0];
y = v.vector[1];
 
for (i = 0; i < width; ++i)
{
int width, height, x0, y0;
const uint8_t *row;
 
if (mask && !mask[i])
goto next;
width = image->bits.width;
height = image->bits.height;
x0 = pixman_fixed_to_int (x - pixman_fixed_e);
y0 = pixman_fixed_to_int (y - pixman_fixed_e);
 
if (repeat_mode == PIXMAN_REPEAT_NONE &&
(y0 < 0 || y0 >= height || x0 < 0 || x0 >= width))
{
buffer[i] = 0;
}
else
{
uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
 
if (repeat_mode != PIXMAN_REPEAT_NONE)
{
repeat (repeat_mode, &x0, width);
repeat (repeat_mode, &y0, height);
}
 
row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;
 
buffer[i] = convert_pixel (row, x0) | mask;
}
 
next:
x += ux;
y += uy;
}
}
 
static force_inline uint32_t
convert_a8r8g8b8 (const uint8_t *row, int x)
{
927,54 → 1114,89
static force_inline uint32_t
convert_r5g6b5 (const uint8_t *row, int x)
{
return CONVERT_0565_TO_0888 (*((uint16_t *)row + x));
return convert_0565_to_0888 (*((uint16_t *)row + x));
}
 
#define MAKE_SEPARABLE_CONVOLUTION_FETCHER(name, format, repeat_mode) \
static uint32_t * \
bits_image_fetch_separable_convolution_affine_ ## name (pixman_iter_t *iter, \
const uint32_t * mask) \
{ \
bits_image_fetch_separable_convolution_affine ( \
iter->image, \
iter->x, iter->y++, \
iter->width, \
iter->buffer, mask, \
convert_ ## format, \
PIXMAN_ ## format, \
repeat_mode); \
\
return iter->buffer; \
}
 
#define MAKE_BILINEAR_FETCHER(name, format, repeat_mode) \
static void \
bits_image_fetch_bilinear_affine_ ## name (pixman_image_t *image, \
int offset, \
int line, \
int width, \
uint32_t * buffer, \
static uint32_t * \
bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t *iter, \
const uint32_t * mask) \
{ \
bits_image_fetch_bilinear_affine (image, offset, line, width, buffer, mask, \
bits_image_fetch_bilinear_affine (iter->image, \
iter->x, iter->y++, \
iter->width, \
iter->buffer, mask, \
convert_ ## format, \
PIXMAN_ ## format, \
repeat_mode); \
} \
extern int no_such_variable
return iter->buffer; \
}
 
MAKE_BILINEAR_FETCHER (pad_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_PAD);
MAKE_BILINEAR_FETCHER (none_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NONE);
MAKE_BILINEAR_FETCHER (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT);
MAKE_BILINEAR_FETCHER (normal_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NORMAL);
MAKE_BILINEAR_FETCHER (pad_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_PAD);
MAKE_BILINEAR_FETCHER (none_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NONE);
MAKE_BILINEAR_FETCHER (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT);
MAKE_BILINEAR_FETCHER (normal_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NORMAL);
MAKE_BILINEAR_FETCHER (pad_a8, a8, PIXMAN_REPEAT_PAD);
MAKE_BILINEAR_FETCHER (none_a8, a8, PIXMAN_REPEAT_NONE);
MAKE_BILINEAR_FETCHER (reflect_a8, a8, PIXMAN_REPEAT_REFLECT);
MAKE_BILINEAR_FETCHER (normal_a8, a8, PIXMAN_REPEAT_NORMAL);
MAKE_BILINEAR_FETCHER (pad_r5g6b5, r5g6b5, PIXMAN_REPEAT_PAD);
MAKE_BILINEAR_FETCHER (none_r5g6b5, r5g6b5, PIXMAN_REPEAT_NONE);
MAKE_BILINEAR_FETCHER (reflect_r5g6b5, r5g6b5, PIXMAN_REPEAT_REFLECT);
MAKE_BILINEAR_FETCHER (normal_r5g6b5, r5g6b5, PIXMAN_REPEAT_NORMAL);
#define MAKE_NEAREST_FETCHER(name, format, repeat_mode) \
static uint32_t * \
bits_image_fetch_nearest_affine_ ## name (pixman_iter_t *iter, \
const uint32_t * mask) \
{ \
bits_image_fetch_nearest_affine (iter->image, \
iter->x, iter->y++, \
iter->width, \
iter->buffer, mask, \
convert_ ## format, \
PIXMAN_ ## format, \
repeat_mode); \
return iter->buffer; \
}
 
#define MAKE_FETCHERS(name, format, repeat_mode) \
MAKE_NEAREST_FETCHER (name, format, repeat_mode) \
MAKE_BILINEAR_FETCHER (name, format, repeat_mode) \
MAKE_SEPARABLE_CONVOLUTION_FETCHER (name, format, repeat_mode)
 
MAKE_FETCHERS (pad_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_PAD)
MAKE_FETCHERS (none_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NONE)
MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT)
MAKE_FETCHERS (normal_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NORMAL)
MAKE_FETCHERS (pad_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_PAD)
MAKE_FETCHERS (none_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NONE)
MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT)
MAKE_FETCHERS (normal_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NORMAL)
MAKE_FETCHERS (pad_a8, a8, PIXMAN_REPEAT_PAD)
MAKE_FETCHERS (none_a8, a8, PIXMAN_REPEAT_NONE)
MAKE_FETCHERS (reflect_a8, a8, PIXMAN_REPEAT_REFLECT)
MAKE_FETCHERS (normal_a8, a8, PIXMAN_REPEAT_NORMAL)
MAKE_FETCHERS (pad_r5g6b5, r5g6b5, PIXMAN_REPEAT_PAD)
MAKE_FETCHERS (none_r5g6b5, r5g6b5, PIXMAN_REPEAT_NONE)
MAKE_FETCHERS (reflect_r5g6b5, r5g6b5, PIXMAN_REPEAT_REFLECT)
MAKE_FETCHERS (normal_r5g6b5, r5g6b5, PIXMAN_REPEAT_NORMAL)
 
static void
bits_image_fetch_solid_32 (pixman_image_t * image,
replicate_pixel_32 (bits_image_t * bits,
int x,
int y,
int width,
uint32_t * buffer,
const uint32_t * mask)
uint32_t * buffer)
{
uint32_t color;
uint32_t *end;
 
color = image->bits.fetch_pixel_32 (&image->bits, 0, 0);
color = bits->fetch_pixel_32 (bits, x, y);
 
end = buffer + width;
while (buffer < end)
982,18 → 1204,17
}
 
static void
bits_image_fetch_solid_64 (pixman_image_t * image,
replicate_pixel_float (bits_image_t * bits,
int x,
int y,
int width,
uint32_t * b,
const uint32_t * unused)
uint32_t * b)
{
uint64_t color;
uint64_t *buffer = (uint64_t *)b;
uint64_t *end;
argb_t color;
argb_t *buffer = (argb_t *)b;
argb_t *end;
 
color = image->bits.fetch_pixel_64 (&image->bits, 0, 0);
color = bits->fetch_pixel_float (bits, x, y);
 
end = buffer + width;
while (buffer < end)
1012,7 → 1233,7
 
if (y < 0 || y >= image->height)
{
memset (buffer, 0, width * (wide? 8 : 4));
memset (buffer, 0, width * (wide? sizeof (argb_t) : 4));
return;
}
 
1020,10 → 1241,10
{
w = MIN (width, -x);
 
memset (buffer, 0, w * (wide ? 8 : 4));
memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4));
 
width -= w;
buffer += w * (wide? 2 : 1);
buffer += w * (wide? 4 : 1);
x += w;
}
 
1032,16 → 1253,16
w = MIN (width, image->width - x);
 
if (wide)
image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
else
image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
 
width -= w;
buffer += w * (wide? 2 : 1);
buffer += w * (wide? 4 : 1);
x += w;
}
 
memset (buffer, 0, width * (wide ? 8 : 4));
memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4));
}
 
static void
1060,6 → 1281,16
while (y >= image->height)
y -= image->height;
 
if (image->width == 1)
{
if (wide)
replicate_pixel_float (image, 0, y, width, buffer);
else
replicate_pixel_32 (image, 0, y, width, buffer);
 
return;
}
 
while (width)
{
while (x < 0)
1070,24 → 1301,26
w = MIN (width, image->width - x);
 
if (wide)
image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
else
image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
 
buffer += w * (wide? 2 : 1);
buffer += w * (wide? 4 : 1);
x += w;
width -= w;
}
}
 
static void
bits_image_fetch_untransformed_32 (pixman_image_t * image,
int x,
int y,
int width,
uint32_t * buffer,
static uint32_t *
bits_image_fetch_untransformed_32 (pixman_iter_t * iter,
const uint32_t * mask)
{
pixman_image_t *image = iter->image;
int x = iter->x;
int y = iter->y;
int width = iter->width;
uint32_t * buffer = iter->buffer;
 
if (image->common.repeat == PIXMAN_REPEAT_NONE)
{
bits_image_fetch_untransformed_repeat_none (
1098,16 → 1331,21
bits_image_fetch_untransformed_repeat_normal (
&image->bits, FALSE, x, y, width, buffer);
}
 
iter->y++;
return buffer;
}
 
static void
bits_image_fetch_untransformed_64 (pixman_image_t * image,
int x,
int y,
int width,
uint32_t * buffer,
const uint32_t * unused)
static uint32_t *
bits_image_fetch_untransformed_float (pixman_iter_t * iter,
const uint32_t *mask)
{
pixman_image_t *image = iter->image;
int x = iter->x;
int y = iter->y;
int width = iter->width;
uint32_t * buffer = iter->buffer;
 
if (image->common.repeat == PIXMAN_REPEAT_NONE)
{
bits_image_fetch_untransformed_repeat_none (
1118,6 → 1356,9
bits_image_fetch_untransformed_repeat_normal (
&image->bits, TRUE, x, y, width, buffer);
}
 
iter->y++;
return buffer;
}
 
typedef struct
1124,18 → 1365,12
{
pixman_format_code_t format;
uint32_t flags;
fetch_scanline_t fetch_32;
fetch_scanline_t fetch_64;
pixman_iter_get_scanline_t get_scanline_32;
pixman_iter_get_scanline_t get_scanline_float;
} fetcher_info_t;
 
static const fetcher_info_t fetcher_info[] =
{
{ PIXMAN_solid,
FAST_PATH_NO_ALPHA_MAP,
bits_image_fetch_solid_32,
bits_image_fetch_solid_64
},
 
{ PIXMAN_any,
(FAST_PATH_NO_ALPHA_MAP |
FAST_PATH_ID_TRANSFORM |
1143,7 → 1378,7
FAST_PATH_NO_PAD_REPEAT |
FAST_PATH_NO_REFLECT_REPEAT),
bits_image_fetch_untransformed_32,
bits_image_fetch_untransformed_64
bits_image_fetch_untransformed_float
},
 
#define FAST_BILINEAR_FLAGS \
1159,13 → 1394,13
{ PIXMAN_a8r8g8b8,
FAST_BILINEAR_FLAGS,
bits_image_fetch_bilinear_no_repeat_8888,
_pixman_image_get_scanline_generic_64
_pixman_image_get_scanline_generic_float
},
 
{ PIXMAN_x8r8g8b8,
FAST_BILINEAR_FLAGS,
bits_image_fetch_bilinear_no_repeat_8888,
_pixman_image_get_scanline_generic_64
_pixman_image_get_scanline_generic_float
},
 
#define GENERAL_BILINEAR_FLAGS \
1175,39 → 1410,76
FAST_PATH_AFFINE_TRANSFORM | \
FAST_PATH_BILINEAR_FILTER)
 
#define GENERAL_NEAREST_FLAGS \
(FAST_PATH_NO_ALPHA_MAP | \
FAST_PATH_NO_ACCESSORS | \
FAST_PATH_HAS_TRANSFORM | \
FAST_PATH_AFFINE_TRANSFORM | \
FAST_PATH_NEAREST_FILTER)
 
#define GENERAL_SEPARABLE_CONVOLUTION_FLAGS \
(FAST_PATH_NO_ALPHA_MAP | \
FAST_PATH_NO_ACCESSORS | \
FAST_PATH_HAS_TRANSFORM | \
FAST_PATH_AFFINE_TRANSFORM | \
FAST_PATH_SEPARABLE_CONVOLUTION_FILTER)
#define SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \
{ PIXMAN_ ## format, \
GENERAL_SEPARABLE_CONVOLUTION_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
bits_image_fetch_separable_convolution_affine_ ## name, \
_pixman_image_get_scanline_generic_float \
},
 
#define BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \
{ PIXMAN_ ## format, \
GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
bits_image_fetch_bilinear_affine_ ## name, \
_pixman_image_get_scanline_generic_64 \
_pixman_image_get_scanline_generic_float \
},
 
BILINEAR_AFFINE_FAST_PATH (pad_a8r8g8b8, a8r8g8b8, PAD)
BILINEAR_AFFINE_FAST_PATH (none_a8r8g8b8, a8r8g8b8, NONE)
BILINEAR_AFFINE_FAST_PATH (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
BILINEAR_AFFINE_FAST_PATH (normal_a8r8g8b8, a8r8g8b8, NORMAL)
BILINEAR_AFFINE_FAST_PATH (pad_x8r8g8b8, x8r8g8b8, PAD)
BILINEAR_AFFINE_FAST_PATH (none_x8r8g8b8, x8r8g8b8, NONE)
BILINEAR_AFFINE_FAST_PATH (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
BILINEAR_AFFINE_FAST_PATH (normal_x8r8g8b8, x8r8g8b8, NORMAL)
BILINEAR_AFFINE_FAST_PATH (pad_a8, a8, PAD)
BILINEAR_AFFINE_FAST_PATH (none_a8, a8, NONE)
BILINEAR_AFFINE_FAST_PATH (reflect_a8, a8, REFLECT)
BILINEAR_AFFINE_FAST_PATH (normal_a8, a8, NORMAL)
BILINEAR_AFFINE_FAST_PATH (pad_r5g6b5, r5g6b5, PAD)
BILINEAR_AFFINE_FAST_PATH (none_r5g6b5, r5g6b5, NONE)
BILINEAR_AFFINE_FAST_PATH (reflect_r5g6b5, r5g6b5, REFLECT)
BILINEAR_AFFINE_FAST_PATH (normal_r5g6b5, r5g6b5, NORMAL)
#define NEAREST_AFFINE_FAST_PATH(name, format, repeat) \
{ PIXMAN_ ## format, \
GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
bits_image_fetch_nearest_affine_ ## name, \
_pixman_image_get_scanline_generic_float \
},
 
#define AFFINE_FAST_PATHS(name, format, repeat) \
SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \
BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \
NEAREST_AFFINE_FAST_PATH(name, format, repeat)
AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD)
AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE)
AFFINE_FAST_PATHS (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
AFFINE_FAST_PATHS (normal_a8r8g8b8, a8r8g8b8, NORMAL)
AFFINE_FAST_PATHS (pad_x8r8g8b8, x8r8g8b8, PAD)
AFFINE_FAST_PATHS (none_x8r8g8b8, x8r8g8b8, NONE)
AFFINE_FAST_PATHS (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
AFFINE_FAST_PATHS (normal_x8r8g8b8, x8r8g8b8, NORMAL)
AFFINE_FAST_PATHS (pad_a8, a8, PAD)
AFFINE_FAST_PATHS (none_a8, a8, NONE)
AFFINE_FAST_PATHS (reflect_a8, a8, REFLECT)
AFFINE_FAST_PATHS (normal_a8, a8, NORMAL)
AFFINE_FAST_PATHS (pad_r5g6b5, r5g6b5, PAD)
AFFINE_FAST_PATHS (none_r5g6b5, r5g6b5, NONE)
AFFINE_FAST_PATHS (reflect_r5g6b5, r5g6b5, REFLECT)
AFFINE_FAST_PATHS (normal_r5g6b5, r5g6b5, NORMAL)
 
/* Affine, no alpha */
{ PIXMAN_any,
(FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM),
bits_image_fetch_affine_no_alpha,
_pixman_image_get_scanline_generic_64
_pixman_image_get_scanline_generic_float
},
 
/* General */
{ PIXMAN_any, 0, bits_image_fetch_general, _pixman_image_get_scanline_generic_64 },
{ PIXMAN_any,
0,
bits_image_fetch_general,
_pixman_image_get_scanline_generic_float
},
 
{ PIXMAN_null },
};
1215,35 → 1487,191
static void
bits_image_property_changed (pixman_image_t *image)
{
_pixman_bits_image_setup_accessors (&image->bits);
}
 
void
_pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter)
{
pixman_format_code_t format = image->common.extended_format_code;
uint32_t flags = image->common.flags;
pixman_format_code_t format = image->common.extended_format_code;
const fetcher_info_t *info;
 
_pixman_bits_image_setup_accessors (&image->bits);
 
info = fetcher_info;
while (info->format != PIXMAN_null)
for (info = fetcher_info; info->format != PIXMAN_null; ++info)
{
if ((info->format == format || info->format == PIXMAN_any) &&
(info->flags & flags) == info->flags)
{
image->common.get_scanline_32 = info->fetch_32;
image->common.get_scanline_64 = info->fetch_64;
break;
if (iter->iter_flags & ITER_NARROW)
{
iter->get_scanline = info->get_scanline_32;
}
else
{
iter->data = info->get_scanline_32;
iter->get_scanline = info->get_scanline_float;
}
return;
}
}
 
info++;
/* Just in case we somehow didn't find a scanline function */
iter->get_scanline = _pixman_iter_get_scanline_noop;
}
 
static uint32_t *
dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
{
pixman_image_t *image = iter->image;
int x = iter->x;
int y = iter->y;
int width = iter->width;
uint32_t * buffer = iter->buffer;
 
image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
if (image->common.alpha_map)
{
uint32_t *alpha;
 
if ((alpha = malloc (width * sizeof (uint32_t))))
{
int i;
 
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
 
image->common.alpha_map->fetch_scanline_32 (
(pixman_image_t *)image->common.alpha_map,
x, y, width, alpha, mask);
 
for (i = 0; i < width; ++i)
{
buffer[i] &= ~0xff000000;
buffer[i] |= (alpha[i] & 0xff000000);
}
 
free (alpha);
}
}
 
return iter->buffer;
}
 
static uint32_t *
dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
{
bits_image_t * image = &iter->image->bits;
int x = iter->x;
int y = iter->y;
int width = iter->width;
argb_t * buffer = (argb_t *)iter->buffer;
 
image->fetch_scanline_float (
(pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask);
if (image->common.alpha_map)
{
argb_t *alpha;
 
if ((alpha = malloc (width * sizeof (argb_t))))
{
int i;
 
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
 
image->common.alpha_map->fetch_scanline_float (
(pixman_image_t *)image->common.alpha_map,
x, y, width, (uint32_t *)alpha, mask);
 
for (i = 0; i < width; ++i)
buffer[i].a = alpha[i].a;
 
free (alpha);
}
}
 
return iter->buffer;
}
 
static void
dest_write_back_narrow (pixman_iter_t *iter)
{
bits_image_t * image = &iter->image->bits;
int x = iter->x;
int y = iter->y;
int width = iter->width;
const uint32_t *buffer = iter->buffer;
 
image->store_scanline_32 (image, x, y, width, buffer);
 
if (image->common.alpha_map)
{
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
 
image->common.alpha_map->store_scanline_32 (
image->common.alpha_map, x, y, width, buffer);
}
 
iter->y++;
}
 
static void
dest_write_back_wide (pixman_iter_t *iter)
{
bits_image_t * image = &iter->image->bits;
int x = iter->x;
int y = iter->y;
int width = iter->width;
const uint32_t *buffer = iter->buffer;
 
image->store_scanline_float (image, x, y, width, buffer);
 
if (image->common.alpha_map)
{
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
 
image->common.alpha_map->store_scanline_float (
image->common.alpha_map, x, y, width, buffer);
}
 
iter->y++;
}
 
void
_pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter)
{
if (iter->iter_flags & ITER_NARROW)
{
if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
(ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
{
iter->get_scanline = _pixman_iter_get_scanline_noop;
}
else
{
iter->get_scanline = dest_get_scanline_narrow;
}
iter->write_back = dest_write_back_narrow;
}
else
{
iter->get_scanline = dest_get_scanline_wide;
iter->write_back = dest_write_back_wide;
}
}
 
static uint32_t *
create_bits (pixman_format_code_t format,
int width,
int height,
int * rowstride_bytes)
int * rowstride_bytes,
pixman_bool_t clear)
{
int stride;
int buf_size;
size_t buf_size;
int bpp;
 
/* what follows is a long-winded way, avoiding any possibility of integer
1252,11 → 1680,11
*/
 
bpp = PIXMAN_FORMAT_BPP (format);
if (pixman_multiply_overflows_int (width, bpp))
if (_pixman_multiply_overflows_int (width, bpp))
return NULL;
 
stride = width * bpp;
if (pixman_addition_overflows_int (stride, 0x1f))
if (_pixman_addition_overflows_int (stride, 0x1f))
return NULL;
 
stride += 0x1f;
1264,7 → 1692,7
 
stride *= sizeof (uint32_t);
 
if (pixman_multiply_overflows_int (height, stride))
if (_pixman_multiply_overflows_size (height, stride))
return NULL;
 
buf_size = height * stride;
1272,43 → 1700,37
if (rowstride_bytes)
*rowstride_bytes = stride;
 
if (clear)
return calloc (buf_size, 1);
else
return malloc (buf_size);
}
 
PIXMAN_EXPORT pixman_image_t *
pixman_image_create_bits (pixman_format_code_t format,
pixman_bool_t
_pixman_bits_image_init (pixman_image_t * image,
pixman_format_code_t format,
int width,
int height,
uint32_t * bits,
int rowstride_bytes)
int rowstride,
pixman_bool_t clear)
{
pixman_image_t *image;
uint32_t *free_me = NULL;
 
/* must be a whole number of uint32_t's
*/
return_val_if_fail (
bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
 
return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
 
if (!bits && width && height)
{
free_me = bits = create_bits (format, width, height, &rowstride_bytes);
if (!bits)
return NULL;
}
int rowstride_bytes;
 
image = _pixman_image_allocate ();
free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear);
 
if (!image)
{
if (free_me)
free (free_me);
if (!bits)
return FALSE;
 
return NULL;
rowstride = rowstride_bytes / (int) sizeof (uint32_t);
}
 
_pixman_image_init (image);
 
image->type = BITS;
image->bits.format = format;
image->bits.width = width;
1317,10 → 1739,7
image->bits.free_me = free_me;
image->bits.read_func = NULL;
image->bits.write_func = NULL;
 
/* The rowstride is stored in number of uint32_t */
image->bits.rowstride = rowstride_bytes / (int) sizeof (uint32_t);
 
image->bits.rowstride = rowstride;
image->bits.indexed = NULL;
 
image->common.property_changed = bits_image_property_changed;
1327,5 → 1746,63
 
_pixman_image_reset_clip_region (image);
 
return TRUE;
}
 
static pixman_image_t *
create_bits_image_internal (pixman_format_code_t format,
int width,
int height,
uint32_t * bits,
int rowstride_bytes,
pixman_bool_t clear)
{
pixman_image_t *image;
 
/* must be a whole number of uint32_t's
*/
return_val_if_fail (
bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
 
return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
 
image = _pixman_image_allocate ();
 
if (!image)
return NULL;
 
if (!_pixman_bits_image_init (image, format, width, height, bits,
rowstride_bytes / (int) sizeof (uint32_t),
clear))
{
free (image);
return NULL;
}
 
return image;
}
 
/* If bits is NULL, a buffer will be allocated and initialized to 0 */
PIXMAN_EXPORT pixman_image_t *
pixman_image_create_bits (pixman_format_code_t format,
int width,
int height,
uint32_t * bits,
int rowstride_bytes)
{
return create_bits_image_internal (
format, width, height, bits, rowstride_bytes, TRUE);
}
 
 
/* If bits is NULL, a buffer will be allocated and _not_ initialized */
PIXMAN_EXPORT pixman_image_t *
pixman_image_create_bits_no_clear (pixman_format_code_t format,
int width,
int height,
uint32_t * bits,
int rowstride_bytes)
{
return create_bits_image_internal (
format, width, height, bits, rowstride_bytes, FALSE);
}