Commit 5433969e authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

gdiplus: Don't use gdi32 to draw to bitmaps with formats it can't handle.

parent af7b8efc
......@@ -78,6 +78,29 @@ static inline REAL deg2rad(REAL degrees)
return M_PI * degrees / 180.0;
}
static inline ARGB color_over(ARGB bg, ARGB fg)
{
BYTE b, g, r, a;
BYTE bg_alpha, fg_alpha;
fg_alpha = (fg>>24)&0xff;
if (fg_alpha == 0xff) return fg;
if (fg_alpha == 0) return bg;
bg_alpha = (((bg>>24)&0xff) * (0xff-fg_alpha)) / 0xff;
if (bg_alpha == 0) return fg;
a = bg_alpha + fg_alpha;
b = ((bg&0xff)*bg_alpha + (fg&0xff)*fg_alpha)*0xff/a;
g = (((bg>>8)&0xff)*bg_alpha + ((fg>>8)&0xff)*fg_alpha)*0xff/a;
r = (((bg>>16)&0xff)*bg_alpha + ((fg>>16)&0xff)*fg_alpha)*0xff/a;
return (a<<24)|(r<<16)|(g<<8)|b;
}
extern const char *debugstr_rectf(CONST RectF* rc);
extern const char *debugstr_pointf(CONST PointF* pt);
......
......@@ -1872,9 +1872,10 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
REAL srcheight, GpUnit srcUnit, GDIPCONST GpImageAttributes* imageAttributes,
DrawImageAbort callback, VOID * callbackData)
{
GpPointF ptf[3];
POINT pti[3];
GpPointF ptf[4];
POINT pti[4];
REAL dx, dy;
GpStatus stat;
TRACE("(%p, %p, %p, %d, %f, %f, %f, %f, %d, %p, %p, %p)\n", graphics, image, points,
count, srcx, srcy, srcwidth, srcheight, srcUnit, imageAttributes, callback,
......@@ -1887,7 +1888,9 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
debugstr_pointf(&points[2]));
memcpy(ptf, points, 3 * sizeof(GpPointF));
transform_and_round_points(graphics, pti, ptf, 3);
ptf[3].X = ptf[2].X + ptf[1].X - ptf[0].X;
ptf[3].Y = ptf[2].Y + ptf[1].Y - ptf[0].Y;
transform_and_round_points(graphics, pti, ptf, 4);
if (image->picture)
{
......@@ -1914,10 +1917,8 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
}
else if (image->type == ImageTypeBitmap && ((GpBitmap*)image)->hbitmap)
{
HDC hdc;
GpBitmap* bitmap = (GpBitmap*)image;
int temp_hdc=0, temp_bitmap=0;
HBITMAP hbitmap, old_hbm=NULL;
int use_software=0;
if (srcUnit == UnitInch)
dx = dy = 96.0; /* FIXME: use the image resolution */
......@@ -1926,6 +1927,89 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
else
return NotImplemented;
if (graphics->image && graphics->image->type == ImageTypeBitmap)
{
GpBitmap *dst_bitmap = (GpBitmap*)graphics->image;
if (!(dst_bitmap->format == PixelFormat16bppRGB555 ||
dst_bitmap->format == PixelFormat24bppRGB ||
dst_bitmap->format == PixelFormat32bppRGB))
use_software = 1;
}
if (use_software)
{
RECT src_area, dst_area;
int i, x, y;
GpMatrix *dst_to_src;
REAL m11, m12, m21, m22, mdx, mdy;
src_area.left = srcx*dx;
src_area.top = srcy*dy;
src_area.right = (srcx+srcwidth)*dx;
src_area.bottom = (srcy+srcheight)*dy;
dst_area.left = dst_area.right = pti[0].x;
dst_area.top = dst_area.bottom = pti[0].y;
for (i=1; i<4; i++)
{
if (dst_area.left > pti[i].x) dst_area.left = pti[i].x;
if (dst_area.right < pti[i].x) dst_area.right = pti[i].x;
if (dst_area.top > pti[i].y) dst_area.top = pti[i].y;
if (dst_area.bottom < pti[i].y) dst_area.bottom = pti[i].y;
}
m11 = (ptf[1].X - ptf[0].X) / srcwidth;
m12 = (ptf[2].X - ptf[0].X) / srcheight;
mdx = ptf[0].X - m11 * srcx - m12 * srcy;
m21 = (ptf[1].Y - ptf[0].Y) / srcwidth;
m22 = (ptf[2].Y - ptf[0].Y) / srcheight;
mdy = ptf[0].Y - m21 * srcx - m22 * srcy;
stat = GdipCreateMatrix2(m11, m12, m21, m22, mdx, mdy, &dst_to_src);
if (stat != Ok) return stat;
stat = GdipInvertMatrix(dst_to_src);
if (stat != Ok)
{
GdipDeleteMatrix(dst_to_src);
return stat;
}
for (x=dst_area.left; x<dst_area.right; x++)
{
for (y=dst_area.top; y<dst_area.bottom; y++)
{
GpPointF src_pointf;
int src_x, src_y;
ARGB src_color, dst_color;
src_pointf.X = x;
src_pointf.Y = y;
GdipTransformMatrixPoints(dst_to_src, &src_pointf, 1);
src_x = roundr(src_pointf.X);
src_y = roundr(src_pointf.Y);
if (src_x < src_area.left || src_x >= src_area.right ||
src_y < src_area.top || src_y >= src_area.bottom)
/* FIXME: Use wrapmode */
continue;
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);
}
else
{
HDC hdc;
int temp_hdc=0, temp_bitmap=0;
HBITMAP hbitmap, old_hbm=NULL;
if (!(bitmap->format == PixelFormat16bppRGB555 ||
bitmap->format == PixelFormat24bppRGB ||
bitmap->format == PixelFormat32bppRGB ||
......@@ -2004,6 +2088,7 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
if (temp_bitmap)
DeleteObject(hbitmap);
}
}
else
{
ERR("GpImage with no IPicture or HBITMAP?!\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment