winex11: Implement rectangular gradients using straight X11 calls.

This commit is contained in:
Alexandre Julliard 2011-11-30 13:09:08 +01:00
parent 4c6807199e
commit 0446707a56
3 changed files with 121 additions and 1 deletions

View File

@ -1493,6 +1493,124 @@ BOOL X11DRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillTy
return TRUE;
}
/**********************************************************************
* X11DRV_GradientFill
*/
BOOL X11DRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
void *grad_array, ULONG ngrad, ULONG mode )
{
X11DRV_PDEVICE *physdev = get_x11drv_dev( dev );
const GRADIENT_RECT *rect = grad_array;
TRIVERTEX v[2];
POINT pt[2];
unsigned int i;
XGCValues val;
/* 4, 8, and 16-bpp use dithering */
if (physdev->depth >= 4 && physdev->depth <= 16) goto fallback;
switch (mode)
{
case GRADIENT_FILL_RECT_H:
val.function = GXcopy;
val.fill_style = FillSolid;
val.line_width = 1;
val.cap_style = CapNotLast;
val.line_style = LineSolid;
wine_tsx11_lock();
XChangeGC( gdi_display, physdev->gc,
GCFunction | GCLineWidth | GCLineStyle | GCCapStyle | GCFillStyle, &val );
wine_tsx11_unlock();
X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
for (i = 0; i < ngrad; i++, rect++)
{
int pos, x, dx;
v[0] = vert_array[rect->UpperLeft];
v[1] = vert_array[rect->LowerRight];
pt[0].x = v[0].x;
pt[0].y = v[0].y;
pt[1].x = v[1].x;
pt[1].y = v[1].y;
LPtoDP( dev->hdc, pt, 2 );
dx = pt[1].x - pt[0].x;
if (!dx) continue;
if (dx < 0) /* swap the colors */
{
v[0] = vert_array[rect->LowerRight];
v[1] = vert_array[rect->UpperLeft];
dx = -dx;
}
for (x = 0, pos = min( pt[0].x, pt[1].x ); x < dx; x++, pos++)
{
COLORREF color = RGB( (v[0].Red * (dx - x) + v[1].Red * x) / dx / 256,
(v[0].Green * (dx - x) + v[1].Green * x) / dx / 256,
(v[0].Blue * (dx - x) + v[1].Blue * x) / dx / 256);
wine_tsx11_lock();
XSetForeground( gdi_display, physdev->gc, X11DRV_PALETTE_ToPhysical( physdev, color ));
XDrawLine( gdi_display, physdev->drawable, physdev->gc,
physdev->dc_rect.left + pos, physdev->dc_rect.top + pt[0].y,
physdev->dc_rect.left + pos, physdev->dc_rect.top + pt[1].y );
wine_tsx11_unlock();
}
}
X11DRV_UnlockDIBSection( physdev, TRUE );
return TRUE;
case GRADIENT_FILL_RECT_V:
val.function = GXcopy;
val.fill_style = FillSolid;
val.line_width = 1;
val.cap_style = CapNotLast;
val.line_style = LineSolid;
wine_tsx11_lock();
XChangeGC( gdi_display, physdev->gc,
GCFunction | GCLineWidth | GCLineStyle | GCCapStyle | GCFillStyle, &val );
wine_tsx11_unlock();
X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
for (i = 0; i < ngrad; i++, rect++)
{
int pos, y, dy;
v[0] = vert_array[rect->UpperLeft];
v[1] = vert_array[rect->LowerRight];
pt[0].x = v[0].x;
pt[0].y = v[0].y;
pt[1].x = v[1].x;
pt[1].y = v[1].y;
LPtoDP( dev->hdc, pt, 2 );
dy = pt[1].y - pt[0].y;
if (!dy) continue;
if (dy < 0) /* swap the colors */
{
v[0] = vert_array[rect->LowerRight];
v[1] = vert_array[rect->UpperLeft];
dy = -dy;
}
for (y = 0, pos = min( pt[0].y, pt[1].y ); y < dy; y++, pos++)
{
COLORREF color = RGB( (v[0].Red * (dy - y) + v[1].Red * y) / dy / 256,
(v[0].Green * (dy - y) + v[1].Green * y) / dy / 256,
(v[0].Blue * (dy - y) + v[1].Blue * y) / dy / 256);
wine_tsx11_lock();
XSetForeground( gdi_display, physdev->gc, X11DRV_PALETTE_ToPhysical( physdev, color ));
XDrawLine( gdi_display, physdev->drawable, physdev->gc,
physdev->dc_rect.left + pt[0].x, physdev->dc_rect.top + pos,
physdev->dc_rect.left + pt[1].x, physdev->dc_rect.top + pos );
wine_tsx11_unlock();
}
}
X11DRV_UnlockDIBSection( physdev, TRUE );
return TRUE;
}
fallback:
dev = GET_NEXT_PHYSDEV( dev, pGradientFill );
return dev->funcs->pGradientFill( dev, vert_array, nvert, grad_array, ngrad, mode );
}
/**********************************************************************
* X11DRV_SetBkColor
*/

View File

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

View File

@ -203,6 +203,8 @@ extern UINT X11DRV_GetSystemPaletteEntries( PHYSDEV dev, UINT start, UINT count,
extern BOOL X11DRV_GetTextExtentExPoint( PHYSDEV dev, LPCWSTR str, INT count, INT maxExt,
LPINT lpnFit, LPINT alpDx, LPSIZE size ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_GetTextMetrics(PHYSDEV dev, TEXTMETRICW *metrics) DECLSPEC_HIDDEN;
extern BOOL X11DRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
void *grad_array, ULONG ngrad, ULONG mode ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_LineTo( PHYSDEV dev, INT x, INT y) DECLSPEC_HIDDEN;
extern BOOL X11DRV_PaintRgn( PHYSDEV dev, HRGN hrgn ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop ) DECLSPEC_HIDDEN;