gdi32: Add a DC driver entry point for GdiGradientFill.

This commit is contained in:
Alexandre Julliard 2011-10-31 23:51:38 +01:00
parent afd962121b
commit 95cba0c0f4
12 changed files with 166 additions and 139 deletions

View File

@ -586,6 +586,7 @@ const struct gdi_dc_funcs dib_driver =
NULL, /* pGetTextExtentExPointI */
NULL, /* pGetTextFace */
NULL, /* pGetTextMetrics */
NULL, /* pGradientFill */
NULL, /* pIntersectClipRect */
NULL, /* pInvertRgn */
dibdrv_LineTo, /* pLineTo */

View File

@ -796,6 +796,7 @@ const struct gdi_dc_funcs null_driver =
nulldrv_GetTextExtentExPointI, /* pGetTextExtentExPointI */
nulldrv_GetTextFace, /* pGetTextFace */
nulldrv_GetTextMetrics, /* pGetTextMetrics */
nulldrv_GradientFill, /* pGradientFill */
nulldrv_IntersectClipRect, /* pIntersectClipRect */
nulldrv_InvertRgn, /* pInvertRgn */
nulldrv_LineTo, /* pLineTo */

View File

@ -97,6 +97,7 @@ static const struct gdi_dc_funcs EMFDRV_Funcs =
NULL, /* pGetTextExtentExPointI */
NULL, /* pGetTextFace */
NULL, /* pGetTextMetrics */
NULL, /* pGradientFill */
EMFDRV_IntersectClipRect, /* pIntersectClipRect */
EMFDRV_InvertRgn, /* pInvertRgn */
EMFDRV_LineTo, /* pLineTo */

View File

@ -7183,6 +7183,7 @@ static const struct gdi_dc_funcs freetype_funcs =
freetype_GetTextExtentExPointI, /* pGetTextExtentExPointI */
freetype_GetTextFace, /* pGetTextFace */
freetype_GetTextMetrics, /* pGetTextMetrics */
NULL, /* pGradientFill */
NULL, /* pIntersectClipRect */
NULL, /* pInvertRgn */
NULL, /* pLineTo */

View File

@ -364,6 +364,8 @@ extern BOOL nulldrv_FrameRgn( PHYSDEV dev, HRGN rgn, HBRUSH brush, INT width, IN
extern LONG nulldrv_GetBitmapBits( HBITMAP bitmap, void *bits, LONG size ) DECLSPEC_HIDDEN;
extern DWORD nulldrv_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info, struct gdi_image_bits *bits, struct bitblt_coords *src ) DECLSPEC_HIDDEN;
extern COLORREF nulldrv_GetNearestColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN;
extern BOOL nulldrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
void * grad_array, ULONG ngrad, ULONG mode ) DECLSPEC_HIDDEN;
extern INT nulldrv_IntersectClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN;
extern BOOL nulldrv_InvertRgn( PHYSDEV dev, HRGN rgn ) DECLSPEC_HIDDEN;
extern BOOL nulldrv_ModifyWorldTransform( PHYSDEV dev, const XFORM *xform, DWORD mode ) DECLSPEC_HIDDEN;

View File

@ -142,6 +142,7 @@ static const struct gdi_dc_funcs MFDRV_Funcs =
NULL, /* pGetTextExtentExPointI */
NULL, /* pGetTextFace */
NULL, /* pGetTextMetrics */
NULL, /* pGradientFill */
MFDRV_IntersectClipRect, /* pIntersectClipRect */
MFDRV_InvertRgn, /* pInvertRgn */
MFDRV_LineTo, /* pLineTo */

View File

@ -226,6 +226,149 @@ 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.@)
*/
@ -1223,147 +1366,19 @@ POINT *GDI_Bezier( const POINT *Points, INT count, INT *nPtsOut )
BOOL WINAPI GdiGradientFill( HDC hdc, TRIVERTEX *vert_array, ULONG nvert,
void * grad_array, ULONG ngrad, ULONG mode )
{
unsigned int i;
DC *dc = get_dc_ptr( hdc );
PHYSDEV physdev;
BOOL ret;
TRACE("vert_array:%p nvert:%d grad_array:%p ngrad:%d\n",
vert_array, nvert, grad_array, ngrad);
TRACE("%p vert_array:%p nvert:%d grad_array:%p ngrad:%d\n", hdc, vert_array, nvert, grad_array, ngrad);
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( hdc, hPen );
pts[0].x = v1->x + x;
pts[0].y = y1;
pts[1].x = v1->x + x;
pts[1].y = y2;
Polyline( hdc, &pts[0], 2 );
DeleteObject( SelectObject(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( hdc, hPen );
pts[0].x = x1;
pts[0].y = v1->y + y;
pts[1].x = x2;
pts[1].y = v1->y + y;
Polyline( hdc, &pts[0], 2 );
DeleteObject( SelectObject(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 */
if (!dc) return FALSE;
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 (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 (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;
update_dc( dc );
physdev = GET_DC_PHYSDEV( dc, pGradientFill );
ret = physdev->funcs->pGradientFill( physdev, vert_array, nvert, grad_array, ngrad, mode );
release_dc_ptr( dc );
return ret;
}
/******************************************************************************

View File

@ -2315,6 +2315,7 @@ const struct gdi_dc_funcs path_driver =
NULL, /* pGetTextExtentExPointI */
NULL, /* pGetTextFace */
NULL, /* pGetTextMetrics */
NULL, /* pGradientFill */
NULL, /* pIntersectClipRect */
NULL, /* pInvertRgn */
pathdrv_LineTo, /* pLineTo */

View File

@ -879,6 +879,7 @@ static const struct gdi_dc_funcs psdrv_funcs =
NULL, /* pGetTextExtentExPointI */
NULL, /* pGetTextFace */
PSDRV_GetTextMetrics, /* pGetTextMetrics */
NULL, /* pGradientFill */
NULL, /* pIntersectClipRect */
NULL, /* pInvertRgn */
PSDRV_LineTo, /* pLineTo */

View File

@ -526,6 +526,7 @@ static const struct gdi_dc_funcs x11drv_funcs =
NULL, /* pGetTextExtentExPointI */
NULL, /* pGetTextFace */
X11DRV_GetTextMetrics, /* pGetTextMetrics */
NULL, /* pGradientFill */
NULL, /* pIntersectClipRect */
NULL, /* pInvertRgn */
X11DRV_LineTo, /* pLineTo */

View File

@ -3071,6 +3071,7 @@ static const struct gdi_dc_funcs xrender_funcs =
NULL, /* pGetTextExtentExPointI */
NULL, /* pGetTextFace */
NULL, /* pGetTextMetrics */
NULL, /* pGradientFill */
NULL, /* pIntersectClipRect */
NULL, /* pInvertRgn */
NULL, /* pLineTo */

View File

@ -115,6 +115,7 @@ struct gdi_dc_funcs
BOOL (*pGetTextExtentExPointI)(PHYSDEV,const WORD*,INT,INT,LPINT,LPINT,LPSIZE);
INT (*pGetTextFace)(PHYSDEV,INT,LPWSTR);
BOOL (*pGetTextMetrics)(PHYSDEV,TEXTMETRICW*);
BOOL (*pGradientFill)(PHYSDEV,TRIVERTEX*,ULONG,void*,ULONG,ULONG);
INT (*pIntersectClipRect)(PHYSDEV,INT,INT,INT,INT);
BOOL (*pInvertRgn)(PHYSDEV,HRGN);
BOOL (*pLineTo)(PHYSDEV,INT,INT);
@ -203,7 +204,7 @@ struct gdi_dc_funcs
};
/* increment this when you change the DC function table */
#define WINE_GDI_DRIVER_VERSION 16
#define WINE_GDI_DRIVER_VERSION 17
static inline PHYSDEV get_physdev_entry_point( PHYSDEV dev, size_t offset )
{