gdiplus: Use a helper function to draw image data from bitmaps in software.

This will make it possible to use the same codepath for non-bitmap graphics
objects and to create a software implementation for other drawing operations.
This commit is contained in:
Vincent Povirk 2010-04-15 14:11:07 -05:00 committed by Alexandre Julliard
parent 32ceee8bf1
commit 9c380b1e8e
1 changed files with 53 additions and 7 deletions

View File

@ -173,6 +173,35 @@ static void transform_and_round_points(GpGraphics *graphics, POINT *pti,
} }
} }
/* Draw non-premultiplied ARGB data to the given graphics object */
static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y,
const BYTE *src, INT src_width, INT src_height, INT src_stride)
{
if (graphics->image && graphics->image->type == ImageTypeBitmap)
{
GpBitmap *dst_bitmap = (GpBitmap*)graphics->image;
INT x, y;
for (x=0; x<src_width; x++)
{
for (y=0; y<src_height; y++)
{
ARGB dst_color, src_color;
GdipBitmapGetPixel(dst_bitmap, x+dst_x, y+dst_y, &dst_color);
src_color = ((ARGB*)(src + src_stride * y))[x];
GdipBitmapSetPixel(dst_bitmap, x+dst_x, y+dst_y, color_over(dst_color, src_color));
}
}
return Ok;
}
else
{
ERR("Not implemented for non-bitmap DC's\n");
return GenericError;
}
}
static ARGB blend_colors(ARGB start, ARGB end, REAL position) static ARGB blend_colors(ARGB start, ARGB end, REAL position)
{ {
ARGB result=0; ARGB result=0;
@ -1939,9 +1968,10 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
if (use_software) if (use_software)
{ {
RECT src_area, dst_area; RECT src_area, dst_area;
int i, x, y; int i, x, y, stride;
GpMatrix *dst_to_src; GpMatrix *dst_to_src;
REAL m11, m12, m21, m22, mdx, mdy; REAL m11, m12, m21, m22, mdx, mdy;
LPBYTE data;
src_area.left = srcx*dx; src_area.left = srcx*dx;
src_area.top = srcy*dy; src_area.top = srcy*dy;
@ -1975,13 +2005,22 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
return stat; return stat;
} }
data = GdipAlloc(sizeof(ARGB) * (dst_area.right - dst_area.left) * (dst_area.bottom - dst_area.top));
if (!data)
{
GdipDeleteMatrix(dst_to_src);
return OutOfMemory;
}
stride = sizeof(ARGB) * (dst_area.right - dst_area.left);
for (x=dst_area.left; x<dst_area.right; x++) for (x=dst_area.left; x<dst_area.right; x++)
{ {
for (y=dst_area.top; y<dst_area.bottom; y++) for (y=dst_area.top; y<dst_area.bottom; y++)
{ {
GpPointF src_pointf; GpPointF src_pointf;
int src_x, src_y; int src_x, src_y;
ARGB src_color, dst_color; ARGB *src_color;
src_pointf.X = x; src_pointf.X = x;
src_pointf.Y = y; src_pointf.Y = y;
@ -1991,18 +2030,25 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
src_x = roundr(src_pointf.X); src_x = roundr(src_pointf.X);
src_y = roundr(src_pointf.Y); src_y = roundr(src_pointf.Y);
src_color = (ARGB*)(data + stride * (y - dst_area.top) + sizeof(ARGB) * (x - dst_area.left));
if (src_x < src_area.left || src_x >= src_area.right || if (src_x < src_area.left || src_x >= src_area.right ||
src_y < src_area.top || src_y >= src_area.bottom) src_y < src_area.top || src_y >= src_area.bottom)
/* FIXME: Use wrapmode */ /* FIXME: Use wrapmode */
continue; *src_color = 0;
else
GdipBitmapGetPixel(bitmap, src_x, src_y, &src_color); GdipBitmapGetPixel(bitmap, src_x, src_y, src_color);
GdipBitmapGetPixel((GpBitmap*)graphics->image, x, y, &dst_color);
GdipBitmapSetPixel((GpBitmap*)graphics->image, x, y, color_over(dst_color, src_color));
} }
} }
GdipDeleteMatrix(dst_to_src); GdipDeleteMatrix(dst_to_src);
stat = alpha_blend_pixels(graphics, dst_area.left, dst_area.top,
data, dst_area.right - dst_area.left, dst_area.bottom - dst_area.top, stride);
GdipFree(data);
return stat;
} }
else else
{ {