gdi32: Use the DIB engine and PutImage for the null driver rectangular gradient implementation.

This commit is contained in:
Alexandre Julliard 2011-11-30 12:21:35 +01:00
parent 157be323b7
commit 4c6807199e
4 changed files with 167 additions and 143 deletions

View File

@ -398,6 +398,163 @@ update_format:
return ERROR_BAD_FORMAT;
}
BOOL nulldrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
void * grad_array, ULONG ngrad, ULONG mode )
{
DC *dc = get_nulldrv_dc( dev );
char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
BITMAPINFO *info = (BITMAPINFO *)buffer;
struct bitblt_coords src, dst;
struct gdi_image_bits bits;
unsigned int i;
DWORD err;
switch(mode)
{
case GRADIENT_FILL_RECT_H:
case GRADIENT_FILL_RECT_V:
{
const GRADIENT_RECT *rect = grad_array;
TRIVERTEX v[2];
for (i = 0; i < ngrad; i++, rect++)
{
v[0] = vert_array[rect->UpperLeft];
v[1] = vert_array[rect->LowerRight];
dst.log_x = v[0].x;
dst.log_y = v[0].y;
dst.log_width = v[1].x - v[0].x;
dst.log_height = v[1].y - v[0].y;
dst.layout = dc->layout;
if (!get_vis_rectangles( dc, &dst, NULL, NULL )) continue;
if (dst.width < 0)
{
if (mode == GRADIENT_FILL_RECT_H) /* swap the colors */
{
v[0] = vert_array[rect->LowerRight];
v[1] = vert_array[rect->UpperLeft];
}
dst.x += dst.width + 1;
dst.width = -dst.width;
}
if (dst.height < 0)
{
if (mode == GRADIENT_FILL_RECT_V) /* swap the colors */
{
v[0] = vert_array[rect->LowerRight];
v[1] = vert_array[rect->UpperLeft];
}
dst.y += dst.height + 1;
dst.height = -dst.height;
}
/* query the bitmap format */
info->bmiHeader.biSize = sizeof(info->bmiHeader);
info->bmiHeader.biPlanes = 1;
info->bmiHeader.biBitCount = 0;
info->bmiHeader.biCompression = BI_RGB;
info->bmiHeader.biXPelsPerMeter = 0;
info->bmiHeader.biYPelsPerMeter = 0;
info->bmiHeader.biClrUsed = 0;
info->bmiHeader.biClrImportant = 0;
info->bmiHeader.biWidth = dst.visrect.right - dst.visrect.left;
info->bmiHeader.biHeight = dst.visrect.bottom - dst.visrect.top;
info->bmiHeader.biSizeImage = 0;
dev = GET_DC_PHYSDEV( dc, pPutImage );
err = dev->funcs->pPutImage( dev, 0, 0, info, NULL, NULL, NULL, 0 );
if (!err || err == ERROR_BAD_FORMAT)
{
if (!(bits.ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ))))
return FALSE;
bits.is_copy = TRUE;
bits.free = free_heap_bits;
/* make src relative to the bitmap */
src = dst;
src.x -= src.visrect.left;
src.y -= src.visrect.top;
offset_rect( &src.visrect, -src.visrect.left, -src.visrect.top );
v[0].x = src.x;
v[0].y = src.y;
v[1].x = src.x + src.width;
v[1].y = src.y + src.height;
err = gradient_bitmapinfo( info, bits.ptr, v, mode );
if (!err) err = dev->funcs->pPutImage( dev, 0, 0, info, &bits, &src, &dst, SRCCOPY );
if (bits.free) bits.free( &bits );
}
if (err) return FALSE;
}
break;
}
case GRADIENT_FILL_TRIANGLE:
for (i = 0; i < ngrad; i++)
{
GRADIENT_TRIANGLE *tri = ((GRADIENT_TRIANGLE *)grad_array) + i;
TRIVERTEX *v1 = vert_array + tri->Vertex1;
TRIVERTEX *v2 = vert_array + tri->Vertex2;
TRIVERTEX *v3 = vert_array + tri->Vertex3;
int y, dy;
if (v1->y > v2->y)
{ TRIVERTEX *t = v1; v1 = v2; v2 = t; }
if (v2->y > v3->y)
{
TRIVERTEX *t = v2; v2 = v3; v3 = t;
if (v1->y > v2->y)
{ t = v1; v1 = v2; v2 = t; }
}
/* v1->y <= v2->y <= v3->y */
dy = v3->y - v1->y;
for (y = 0; y < dy; y++)
{
/* v1->y <= y < v3->y */
TRIVERTEX *v = y < (v2->y - v1->y) ? v1 : v3;
/* (v->y <= y < v2->y) || (v2->y <= y < v->y) */
int dy2 = v2->y - v->y;
int y2 = y + v1->y - v->y;
int x1 = (v3->x * y + v1->x * (dy - y )) / dy;
int x2 = (v2->x * y2 + v-> x * (dy2 - y2)) / dy2;
int r1 = (v3->Red * y + v1->Red * (dy - y )) / dy;
int r2 = (v2->Red * y2 + v-> Red * (dy2 - y2)) / dy2;
int g1 = (v3->Green * y + v1->Green * (dy - y )) / dy;
int g2 = (v2->Green * y2 + v-> Green * (dy2 - y2)) / dy2;
int b1 = (v3->Blue * y + v1->Blue * (dy - y )) / dy;
int b2 = (v2->Blue * y2 + v-> Blue * (dy2 - y2)) / dy2;
int x;
if (x1 < x2)
{
int dx = x2 - x1;
for (x = 0; x < dx; x++)
SetPixel (dev->hdc, x + x1, y + v1->y, RGB(
(r1 * (dx - x) + r2 * x) / dx >> 8,
(g1 * (dx - x) + g2 * x) / dx >> 8,
(b1 * (dx - x) + b2 * x) / dx >> 8));
}
else
{
int dx = x1 - x2;
for (x = 0; x < dx; x++)
SetPixel (dev->hdc, x + x2, y + v1->y, RGB(
(r2 * (dx - x) + r1 * x) / dx >> 8,
(g2 * (dx - x) + g1 * x) / dx >> 8,
(b2 * (dx - x) + b1 * x) / dx >> 8));
}
}
}
break;
default:
return FALSE;
}
return TRUE;
}
/***********************************************************************
* PatBlt (GDI32.@)
*/

View File

@ -1240,6 +1240,15 @@ DWORD blend_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bitbl
return blend_rect( &dst_dib, &dst->visrect, &src_dib, &src->visrect, NULL, blend );
}
DWORD gradient_bitmapinfo( const BITMAPINFO *info, void *bits, TRIVERTEX *v, int mode )
{
dib_info dib;
if (!init_dib_info_from_bitmapinfo( &dib, info, bits, 0 )) return ERROR_BAD_FORMAT;
gradient_rect( &dib, v, mode, 0 );
return ERROR_SUCCESS;
}
/***********************************************************************
* dibdrv_StretchBlt
*/

View File

@ -246,6 +246,7 @@ extern DWORD stretch_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, str
extern DWORD blend_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bitblt_coords *src,
const BITMAPINFO *dst_info, void *dst_bits, struct bitblt_coords *dst,
BLENDFUNCTION blend ) DECLSPEC_HIDDEN;
extern DWORD gradient_bitmapinfo( const BITMAPINFO *info, void *bits, TRIVERTEX *v, int mode ) DECLSPEC_HIDDEN;
extern BOOL render_aa_text_bitmapinfo( HDC hdc, BITMAPINFO *info, struct gdi_image_bits *bits,
struct bitblt_coords *src, INT x, INT y, UINT flags,
UINT aa_flags, LPCWSTR str, UINT count, const INT *dx ) DECLSPEC_HIDDEN;

View File

@ -226,149 +226,6 @@ BOOL nulldrv_PolylineTo( PHYSDEV dev, const POINT *points, INT count )
return ret;
}
BOOL nulldrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
void * grad_array, ULONG ngrad, ULONG mode )
{
unsigned int i;
switch(mode)
{
case GRADIENT_FILL_RECT_H:
for(i = 0; i < ngrad; i++)
{
GRADIENT_RECT *rect = ((GRADIENT_RECT *)grad_array) + i;
TRIVERTEX *v1 = vert_array + rect->UpperLeft;
TRIVERTEX *v2 = vert_array + rect->LowerRight;
int y1 = v1->y < v2->y ? v1->y : v2->y;
int y2 = v2->y > v1->y ? v2->y : v1->y;
int x, dx;
if (v1->x > v2->x)
{
TRIVERTEX *t = v2;
v2 = v1;
v1 = t;
}
dx = v2->x - v1->x;
for (x = 0; x < dx; x++)
{
POINT pts[2];
HPEN hPen, hOldPen;
hPen = CreatePen( PS_SOLID, 1, RGB(
(v1->Red * (dx - x) + v2->Red * x) / dx >> 8,
(v1->Green * (dx - x) + v2->Green * x) / dx >> 8,
(v1->Blue * (dx - x) + v2->Blue * x) / dx >> 8));
hOldPen = SelectObject( dev->hdc, hPen );
pts[0].x = v1->x + x;
pts[0].y = y1;
pts[1].x = v1->x + x;
pts[1].y = y2;
Polyline( dev->hdc, &pts[0], 2 );
DeleteObject( SelectObject(dev->hdc, hOldPen ) );
}
}
break;
case GRADIENT_FILL_RECT_V:
for(i = 0; i < ngrad; i++)
{
GRADIENT_RECT *rect = ((GRADIENT_RECT *)grad_array) + i;
TRIVERTEX *v1 = vert_array + rect->UpperLeft;
TRIVERTEX *v2 = vert_array + rect->LowerRight;
int x1 = v1->x < v2->x ? v1->x : v2->x;
int x2 = v2->x > v1->x ? v2->x : v1->x;
int y, dy;
if (v1->y > v2->y)
{
TRIVERTEX *t = v2;
v2 = v1;
v1 = t;
}
dy = v2->y - v1->y;
for (y = 0; y < dy; y++)
{
POINT pts[2];
HPEN hPen, hOldPen;
hPen = CreatePen( PS_SOLID, 1, RGB(
(v1->Red * (dy - y) + v2->Red * y) / dy >> 8,
(v1->Green * (dy - y) + v2->Green * y) / dy >> 8,
(v1->Blue * (dy - y) + v2->Blue * y) / dy >> 8));
hOldPen = SelectObject( dev->hdc, hPen );
pts[0].x = x1;
pts[0].y = v1->y + y;
pts[1].x = x2;
pts[1].y = v1->y + y;
Polyline( dev->hdc, &pts[0], 2 );
DeleteObject( SelectObject(dev->hdc, hOldPen ) );
}
}
break;
case GRADIENT_FILL_TRIANGLE:
for (i = 0; i < ngrad; i++)
{
GRADIENT_TRIANGLE *tri = ((GRADIENT_TRIANGLE *)grad_array) + i;
TRIVERTEX *v1 = vert_array + tri->Vertex1;
TRIVERTEX *v2 = vert_array + tri->Vertex2;
TRIVERTEX *v3 = vert_array + tri->Vertex3;
int y, dy;
if (v1->y > v2->y)
{ TRIVERTEX *t = v1; v1 = v2; v2 = t; }
if (v2->y > v3->y)
{
TRIVERTEX *t = v2; v2 = v3; v3 = t;
if (v1->y > v2->y)
{ t = v1; v1 = v2; v2 = t; }
}
/* v1->y <= v2->y <= v3->y */
dy = v3->y - v1->y;
for (y = 0; y < dy; y++)
{
/* v1->y <= y < v3->y */
TRIVERTEX *v = y < (v2->y - v1->y) ? v1 : v3;
/* (v->y <= y < v2->y) || (v2->y <= y < v->y) */
int dy2 = v2->y - v->y;
int y2 = y + v1->y - v->y;
int x1 = (v3->x * y + v1->x * (dy - y )) / dy;
int x2 = (v2->x * y2 + v-> x * (dy2 - y2)) / dy2;
int r1 = (v3->Red * y + v1->Red * (dy - y )) / dy;
int r2 = (v2->Red * y2 + v-> Red * (dy2 - y2)) / dy2;
int g1 = (v3->Green * y + v1->Green * (dy - y )) / dy;
int g2 = (v2->Green * y2 + v-> Green * (dy2 - y2)) / dy2;
int b1 = (v3->Blue * y + v1->Blue * (dy - y )) / dy;
int b2 = (v2->Blue * y2 + v-> Blue * (dy2 - y2)) / dy2;
int x;
if (x1 < x2)
{
int dx = x2 - x1;
for (x = 0; x < dx; x++)
SetPixel (dev->hdc, x + x1, y + v1->y, RGB(
(r1 * (dx - x) + r2 * x) / dx >> 8,
(g1 * (dx - x) + g2 * x) / dx >> 8,
(b1 * (dx - x) + b2 * x) / dx >> 8));
}
else
{
int dx = x1 - x2;
for (x = 0; x < dx; x++)
SetPixel (dev->hdc, x + x2, y + v1->y, RGB(
(r2 * (dx - x) + r1 * x) / dx >> 8,
(g2 * (dx - x) + g1 * x) / dx >> 8,
(b2 * (dx - x) + b1 * x) / dx >> 8));
}
}
}
break;
default:
return FALSE;
}
return TRUE;
}
/***********************************************************************
* LineTo (GDI32.@)
*/