Commit 0b38f167 authored by Alexandre Julliard's avatar Alexandre Julliard

gdi32: Reimplement RoundRect in paths to avoid calling imprecise arc helper functions.

parent 1fcf8f54
......@@ -896,59 +896,6 @@ static BOOL pathdrv_LineTo( PHYSDEV dev, INT x, INT y )
/*************************************************************
* pathdrv_RoundRect
*
* FIXME: it adds the same entries to the path as windows does, but there
* is an error in the bezier drawing code so that there are small pixel-size
* gaps when the resulting path is drawn by StrokePath()
*/
static BOOL pathdrv_RoundRect( PHYSDEV dev, INT x1, INT y1, INT x2, INT y2, INT ell_width, INT ell_height )
{
struct path_physdev *physdev = get_path_physdev( dev );
POINT corners[2], pointTemp;
FLOAT_POINT ellCorners[2];
PATH_CheckCorners(dev->hdc,corners,x1,y1,x2,y2);
/* Add points to the roundrect path */
ellCorners[0].x = corners[1].x-ell_width;
ellCorners[0].y = corners[0].y;
ellCorners[1].x = corners[1].x;
ellCorners[1].y = corners[0].y+ell_height;
if(!PATH_DoArcPart(physdev->path, ellCorners, 0, -M_PI_2, PT_MOVETO))
return FALSE;
pointTemp.x = corners[0].x+ell_width/2;
pointTemp.y = corners[0].y;
if(!PATH_AddEntry(physdev->path, &pointTemp, PT_LINETO))
return FALSE;
ellCorners[0].x = corners[0].x;
ellCorners[1].x = corners[0].x+ell_width;
if(!PATH_DoArcPart(physdev->path, ellCorners, -M_PI_2, -M_PI, 0))
return FALSE;
pointTemp.x = corners[0].x;
pointTemp.y = corners[1].y-ell_height/2;
if(!PATH_AddEntry(physdev->path, &pointTemp, PT_LINETO))
return FALSE;
ellCorners[0].y = corners[1].y-ell_height;
ellCorners[1].y = corners[1].y;
if(!PATH_DoArcPart(physdev->path, ellCorners, M_PI, M_PI_2, 0))
return FALSE;
pointTemp.x = corners[1].x-ell_width/2;
pointTemp.y = corners[1].y;
if(!PATH_AddEntry(physdev->path, &pointTemp, PT_LINETO))
return FALSE;
ellCorners[0].x = corners[1].x-ell_width;
ellCorners[1].x = corners[1].x;
if(!PATH_DoArcPart(physdev->path, ellCorners, M_PI_2, 0, 0))
return FALSE;
/* Close the roundrect figure */
close_figure( physdev->path );
return TRUE;
}
/*************************************************************
* pathdrv_Rectangle
*/
static BOOL pathdrv_Rectangle( PHYSDEV dev, INT x1, INT y1, INT x2, INT y2 )
......@@ -974,6 +921,80 @@ static BOOL pathdrv_Rectangle( PHYSDEV dev, INT x1, INT y1, INT x2, INT y2 )
}
/*************************************************************
* pathdrv_RoundRect
*/
static BOOL pathdrv_RoundRect( PHYSDEV dev, INT x1, INT y1, INT x2, INT y2, INT ell_width, INT ell_height )
{
const double factor = 0.55428475; /* 4 / 3 * (sqrt(2) - 1) */
struct path_physdev *physdev = get_path_physdev( dev );
POINT corners[2], ellipse[2], points[16];
BYTE *type;
double width, height;
if (!ell_width || !ell_height) return pathdrv_Rectangle( dev, x1, y1, x2, y2 );
if (!PATH_CheckCorners( dev->hdc, corners, x1, y1, x2, y2 )) return TRUE;
ellipse[0].x = ellipse[0].y = 0;
ellipse[1].x = ell_width;
ellipse[1].y = ell_height;
LPtoDP( dev->hdc, (POINT *)&ellipse, 2 );
ell_width = min( abs( ellipse[1].x - ellipse[0].x ), corners[1].x - corners[0].x );
ell_height = min( abs( ellipse[1].y - ellipse[0].y ), corners[1].y - corners[0].y );
width = ell_width / 2.0;
height = ell_height / 2.0;
/* starting point */
points[0].x = corners[1].x;
points[0].y = corners[0].y + GDI_ROUND( height );
/* first curve */
points[1].x = corners[1].x;
points[1].y = corners[0].y + GDI_ROUND( height * (1 - factor) );
points[2].x = corners[1].x - GDI_ROUND( width * (1 - factor) );
points[2].y = corners[0].y;
points[3].x = corners[1].x - GDI_ROUND( width );
points[3].y = corners[0].y;
/* horizontal line */
points[4].x = corners[0].x + GDI_ROUND( width );
points[4].y = corners[0].y;
/* second curve */
points[5].x = corners[0].x + GDI_ROUND( width * (1 - factor) );
points[5].y = corners[0].y;
points[6].x = corners[0].x;
points[6].y = corners[0].y + GDI_ROUND( height * (1 - factor) );
points[7].x = corners[0].x;
points[7].y = corners[0].y + GDI_ROUND( height );
/* vertical line */
points[8].x = corners[0].x;
points[8].y = corners[1].y - GDI_ROUND( height );
/* third curve */
points[9].x = corners[0].x;
points[9].y = corners[1].y - GDI_ROUND( height * (1 - factor) );
points[10].x = corners[0].x + GDI_ROUND( width * (1 - factor) );
points[10].y = corners[1].y;
points[11].x = corners[0].x + GDI_ROUND( width );
points[11].y = corners[1].y;
/* horizontal line */
points[12].x = corners[1].x - GDI_ROUND( width );
points[12].y = corners[1].y;
/* fourth curve */
points[13].x = corners[1].x - GDI_ROUND( width * (1 - factor) );
points[13].y = corners[1].y;
points[14].x = corners[1].x;
points[14].y = corners[1].y - GDI_ROUND( height * (1 - factor) );
points[15].x = corners[1].x;
points[15].y = corners[1].y - GDI_ROUND( height );
if (GetArcDirection( dev->hdc ) == AD_CLOCKWISE) reverse_points( points, 16 );
if (!(type = add_points( physdev->path, points, 16, PT_BEZIERTO ))) return FALSE;
type[0] = PT_MOVETO;
type[4] = type[8] = type[12] = PT_LINETO;
close_figure( physdev->path );
return TRUE;
}
/* PATH_Arc
*
* Should be called when a call to Arc is performed on a DC that has
......
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