Commit 704c6750 authored by Mark Dufour's avatar Mark Dufour Committed by Alexandre Julliard

Make the functions Pie, Chord, RoundRect, AngleArc, PolyDraw and

Ellipse work with an open path.
parent d0ff2ec0
......@@ -7,6 +7,8 @@
*/
#include <string.h>
#include <stdlib.h>
#include "dc.h"
#include "bitmap.h"
#include "heap.h"
......@@ -128,7 +130,7 @@ BOOL WINAPI Arc( HDC hdc, INT left, INT top, INT right,
if (dc)
{
if(PATH_IsPathOpen(dc->w.path))
ret = PATH_Arc(dc, left, top, right, bottom, xstart, ystart, xend, yend);
ret = PATH_Arc(dc, left, top, right, bottom, xstart, ystart, xend, yend,0);
else if (dc->funcs->pArc)
ret = dc->funcs->pArc(dc,left,top,right,bottom,xstart,ystart,xend,yend);
GDI_ReleaseObj( hdc );
......@@ -197,14 +199,14 @@ BOOL WINAPI Pie( HDC hdc, INT left, INT top,
{
BOOL ret = FALSE;
DC * dc = DC_GetDCUpdate( hdc );
if (dc)
{
if (PATH_IsPathOpen(dc->w.path))
FIXME("-> Path: stub\n");
else if (dc->funcs->pPie)
ret = dc->funcs->pPie(dc,left,top,right,bottom,xstart,ystart,xend,yend);
GDI_ReleaseObj( hdc );
}
if (!dc) return FALSE;
if(PATH_IsPathOpen(dc->w.path))
ret = PATH_Arc(dc,left,top,right,bottom,xstart,ystart,xend,yend,2);
else if(dc->funcs->pPie)
ret = dc->funcs->pPie(dc,left,top,right,bottom,xstart,ystart,xend,yend);
GDI_ReleaseObj( hdc );
return ret;
}
......@@ -229,14 +231,14 @@ BOOL WINAPI Chord( HDC hdc, INT left, INT top,
{
BOOL ret = FALSE;
DC * dc = DC_GetDCUpdate( hdc );
if (dc)
{
if(PATH_IsPathOpen(dc->w.path))
FIXME("-> Path: stub\n");
else if (dc->funcs->pChord)
ret = dc->funcs->pChord(dc,left,top,right,bottom,xstart,ystart,xend,yend);
GDI_ReleaseObj( hdc );
}
if (!dc) return FALSE;
if(PATH_IsPathOpen(dc->w.path))
ret = PATH_Arc(dc,left,top,right,bottom,xstart,ystart,xend,yend,1);
else if(dc->funcs->pChord)
ret = dc->funcs->pChord(dc,left,top,right,bottom,xstart,ystart,xend,yend);
GDI_ReleaseObj( hdc );
return ret;
}
......@@ -259,14 +261,14 @@ BOOL WINAPI Ellipse( HDC hdc, INT left, INT top,
{
BOOL ret = FALSE;
DC * dc = DC_GetDCUpdate( hdc );
if (dc)
{
if(PATH_IsPathOpen(dc->w.path))
FIXME("-> Path: stub\n");
else if (dc->funcs->pEllipse)
ret = dc->funcs->pEllipse(dc,left,top,right,bottom);
GDI_ReleaseObj( hdc );
}
if (!dc) return FALSE;
if(PATH_IsPathOpen(dc->w.path))
ret = PATH_Ellipse(dc,left,top,right,bottom);
else if (dc->funcs->pEllipse)
ret = dc->funcs->pEllipse(dc,left,top,right,bottom);
GDI_ReleaseObj( hdc );
return ret;
}
......@@ -323,7 +325,7 @@ BOOL WINAPI RoundRect( HDC hdc, INT left, INT top, INT right,
if (dc)
{
if(PATH_IsPathOpen(dc->w.path))
FIXME("-> Path: stub\n");
ret = PATH_RoundRect(dc,left,top,right,bottom,ell_width,ell_height);
else if (dc->funcs->pRoundRect)
ret = dc->funcs->pRoundRect(dc,left,top,right,bottom,ell_width,ell_height);
GDI_ReleaseObj( hdc );
......@@ -1016,12 +1018,10 @@ BOOL WINAPI PolyBezierTo( HDC hdc, const POINT* lppt, DWORD cPoints )
/***********************************************************************
* AngleArc (GDI32.5)
*
*/
BOOL WINAPI AngleArc(HDC hdc, INT x, INT y, DWORD dwRadius,
FLOAT eStartAngle, FLOAT eSweepAngle)
BOOL WINAPI AngleArc(HDC hdc, INT x, INT y, DWORD dwRadius, FLOAT eStartAngle, FLOAT eSweepAngle)
{
int x1,y1,x2,y2;
INT x1,y1,x2,y2, arcdir;
BOOL result;
DC *dc;
......@@ -1034,11 +1034,16 @@ BOOL WINAPI AngleArc(HDC hdc, INT x, INT y, DWORD dwRadius,
if(dc->funcs->pAngleArc)
{
result = dc->funcs->pAngleArc( dc, x, y, dwRadius, eStartAngle, eSweepAngle );
GDI_ReleaseObj( hdc );
return result;
}
GDI_ReleaseObj( hdc );
/* AngleArc always works counterclockwise */
arcdir = GetArcDirection( hdc );
SetArcDirection( hdc, AD_COUNTERCLOCKWISE );
x1 = x + cos(eStartAngle*M_PI/180) * dwRadius;
y1 = y - sin(eStartAngle*M_PI/180) * dwRadius;
x2 = x + cos((eStartAngle+eSweepAngle)*M_PI/180) * dwRadius;
......@@ -1053,12 +1058,12 @@ BOOL WINAPI AngleArc(HDC hdc, INT x, INT y, DWORD dwRadius,
x2, y2, x1, y1 );
if( result ) MoveToEx( hdc, x2, y2, NULL );
SetArcDirection( hdc, arcdir );
return result;
}
/***********************************************************************
* PolyDraw (GDI32.270)
*
*/
BOOL WINAPI PolyDraw(HDC hdc, const POINT *lppt, const BYTE *lpbTypes,
DWORD cCount)
......@@ -1091,11 +1096,12 @@ BOOL WINAPI PolyDraw(HDC hdc, const POINT *lppt, const BYTE *lpbTypes,
}
/* if no moveto occurs, we will close the figure here */
lastmove.x = dc->w.CursPosX;
lastmove.x = dc->w.CursPosX;
lastmove.y = dc->w.CursPosY;
/* now let's draw */
for( i = 0; i < cCount; i++ )
{
if( lpbTypes[i] == PT_MOVETO )
{
MoveToEx( hdc, lppt[i].x, lppt[i].y, NULL );
......@@ -1103,24 +1109,24 @@ BOOL WINAPI PolyDraw(HDC hdc, const POINT *lppt, const BYTE *lpbTypes,
lastmove.y = dc->w.CursPosY;
}
else if( lpbTypes[i] & PT_LINETO )
{
LineTo( hdc, lppt[i].x, lppt[i].y );
if( lpbTypes[i] & PT_CLOSEFIGURE )
LineTo( hdc, lastmove.x, lastmove.y );
}
else if( lpbTypes[i] & PT_BEZIERTO )
{
/* optimizeme: multiple BezierTo's with one PolyBezierTo call */
PolyBezierTo( hdc, &lppt[i], 3 );
PolyBezierTo( hdc, &lppt[i], 3 );
i += 2;
if( lpbTypes[i] & PT_CLOSEFIGURE )
LineTo( hdc, lastmove.x, lastmove.y );
}
else
return FALSE;
if( lpbTypes[i] & PT_CLOSEFIGURE )
{
if( PATH_IsPathOpen( dc->w.path ) )
CloseFigure( hdc );
else
LineTo( hdc, lastmove.x, lastmove.y );
}
}
return TRUE;
}
......
......@@ -70,8 +70,6 @@ DEFAULT_DEBUG_CHANNEL(gdi)
static BOOL PATH_PathToRegion(GdiPath *pPath, INT nPolyFillMode,
HRGN *pHrgn);
static void PATH_EmptyPath(GdiPath *pPath);
static BOOL PATH_AddEntry(GdiPath *pPath, const POINT *pPoint,
BYTE flags);
static BOOL PATH_ReserveEntries(GdiPath *pPath, INT numEntries);
static BOOL PATH_DoArcPart(GdiPath *pPath, FLOAT_POINT corners[],
double angleStart, double angleEnd, BOOL addMoveTo);
......@@ -79,6 +77,7 @@ static void PATH_ScaleNormalizedPoint(FLOAT_POINT corners[], double x,
double y, POINT *pPoint);
static void PATH_NormalizePoint(FLOAT_POINT corners[], const FLOAT_POINT
*pPoint, double *pX, double *pY);
static BOOL PATH_CheckCorners(DC *dc, POINT corners[], INT x1, INT y1, INT x2, INT y2);
/***********************************************************************
......@@ -618,6 +617,67 @@ BOOL PATH_LineTo(DC *dc, INT x, INT y)
return PATH_AddEntry(pPath, &point, PT_LINETO);
}
/* PATH_RoundRect
*
* Should be called when a call to RoundRect is performed on a DC that has
* an open path. Returns TRUE if successful, else FALSE.
*
* 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()
*/
BOOL PATH_RoundRect(DC *dc, INT x1, INT y1, INT x2, INT y2, INT ell_width, INT ell_height)
{
GdiPath *pPath = &dc->w.path;
POINT corners[2], pointTemp;
FLOAT_POINT ellCorners[2];
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
if(!PATH_CheckCorners(dc,corners,x1,y1,x2,y2))
return FALSE;
/* 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(pPath, ellCorners, 0, -M_PI_2, TRUE))
return FALSE;
pointTemp.x = corners[0].x+ell_width/2;
pointTemp.y = corners[0].y;
if(!PATH_AddEntry(pPath, &pointTemp, PT_LINETO))
return FALSE;
ellCorners[0].x = corners[0].x;
ellCorners[1].x = corners[0].x+ell_width;
if(!PATH_DoArcPart(pPath, ellCorners, -M_PI_2, -M_PI, FALSE))
return FALSE;
pointTemp.x = corners[0].x;
pointTemp.y = corners[1].y-ell_height/2;
if(!PATH_AddEntry(pPath, &pointTemp, PT_LINETO))
return FALSE;
ellCorners[0].y = corners[1].y-ell_height;
ellCorners[1].y = corners[1].y;
if(!PATH_DoArcPart(pPath, ellCorners, M_PI, M_PI_2, FALSE))
return FALSE;
pointTemp.x = corners[1].x-ell_width/2;
pointTemp.y = corners[1].y;
if(!PATH_AddEntry(pPath, &pointTemp, PT_LINETO))
return FALSE;
ellCorners[0].x = corners[1].x-ell_width;
ellCorners[1].x = corners[1].x;
if(!PATH_DoArcPart(pPath, ellCorners, M_PI_2, 0, FALSE))
return FALSE;
/* Close the roundrect figure */
if(!CloseFigure(dc->hSelf))
return FALSE;
return TRUE;
}
/* PATH_Rectangle
*
* Should be called when a call to Rectangle is performed on a DC that has
......@@ -627,40 +687,13 @@ BOOL PATH_Rectangle(DC *dc, INT x1, INT y1, INT x2, INT y2)
{
GdiPath *pPath = &dc->w.path;
POINT corners[2], pointTemp;
INT temp;
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
/* Convert points to device coordinates */
corners[0].x=x1;
corners[0].y=y1;
corners[1].x=x2;
corners[1].y=y2;
if(!LPtoDP(dc->hSelf, corners, 2))
if(!PATH_CheckCorners(dc,corners,x1,y1,x2,y2))
return FALSE;
/* Make sure first corner is top left and second corner is bottom right */
if(corners[0].x>corners[1].x)
{
temp=corners[0].x;
corners[0].x=corners[1].x;
corners[1].x=temp;
}
if(corners[0].y>corners[1].y)
{
temp=corners[0].y;
corners[0].y=corners[1].y;
corners[1].y=temp;
}
/* In GM_COMPATIBLE, don't include bottom and right edges */
if(dc->w.GraphicsMode==GM_COMPATIBLE)
{
corners[1].x--;
corners[1].y--;
}
/* Close any previous figure */
if(!CloseFigure(dc->hSelf))
......@@ -703,25 +736,27 @@ BOOL PATH_Rectangle(DC *dc, INT x1, INT y1, INT x2, INT y2)
*/
BOOL PATH_Ellipse(DC *dc, INT x1, INT y1, INT x2, INT y2)
{
/* TODO: This should probably be revised to call PATH_AngleArc */
/* (once it exists) */
return PATH_Arc(dc, x1, y1, x2, y2, x1, (y1+y2)/2, x1, (y1+y2)/2);
return( PATH_Arc(dc, x1, y1, x2, y2, x1, (y1+y2)/2, x1, (y1+y2)/2,0) &&
CloseFigure(dc->hSelf) );
}
/* PATH_Arc
*
* Should be called when a call to Arc is performed on a DC that has
* an open path. This adds up to five Bezier splines representing the arc
* to the path. Returns TRUE if successful, else FALSE.
* to the path. When 'lines' is 1, we add 1 extra line to get a chord,
* and when 'lines' is 2, we add 2 extra lines to get a pie.
* Returns TRUE if successful, else FALSE.
*/
BOOL PATH_Arc(DC *dc, INT x1, INT y1, INT x2, INT y2,
INT xStart, INT yStart, INT xEnd, INT yEnd)
INT xStart, INT yStart, INT xEnd, INT yEnd, INT lines)
{
GdiPath *pPath = &dc->w.path;
double angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant=0.0;
/* Initialize angleEndQuadrant to silence gcc's warning */
double x, y;
FLOAT_POINT corners[2], pointStart, pointEnd;
POINT centre;
BOOL start, end;
INT temp;
......@@ -732,8 +767,6 @@ BOOL PATH_Arc(DC *dc, INT x1, INT y1, INT x2, INT y2,
if(pPath->state!=PATH_Open)
return FALSE;
/* FIXME: Do we have to close the current figure? */
/* Check for zero height / width */
/* FIXME: Only in GM_COMPATIBLE? */
if(x1==x2 || y1==y2)
......@@ -839,6 +872,20 @@ BOOL PATH_Arc(DC *dc, INT x1, INT y1, INT x2, INT y2,
start=FALSE;
} while(!end);
/* chord: close figure. pie: add line and close figure */
if(lines==1)
{
if(!CloseFigure(dc->hSelf))
return FALSE;
}
else if(lines==2)
{
centre.x = (corners[0].x+corners[1].x)/2;
centre.y = (corners[0].y+corners[1].y)/2;
if(!PATH_AddEntry(pPath, &centre, PT_LINETO | PT_CLOSEFIGURE))
return FALSE;
}
return TRUE;
}
......@@ -1016,9 +1063,47 @@ BOOL PATH_PolyPolyline( DC *dc, const POINT* pts, const DWORD* counts,
* Internal functions
*/
/* PATH_CheckCorners
*
* Helper function for PATH_RoundRect() and PATH_Rectangle()
*/
static BOOL PATH_CheckCorners(DC *dc, POINT corners[], INT x1, INT y1, INT x2, INT y2)
{
INT temp;
/* Convert points to device coordinates */
corners[0].x=x1;
corners[0].y=y1;
corners[1].x=x2;
corners[1].y=y2;
if(!LPtoDP(dc->hSelf, corners, 2))
return FALSE;
/* Make sure first corner is top left and second corner is bottom right */
if(corners[0].x>corners[1].x)
{
temp=corners[0].x;
corners[0].x=corners[1].x;
corners[1].x=temp;
}
if(corners[0].y>corners[1].y)
{
temp=corners[0].y;
corners[0].y=corners[1].y;
corners[1].y=temp;
}
/* In GM_COMPATIBLE, don't include bottom and right edges */
if(dc->w.GraphicsMode==GM_COMPATIBLE)
{
corners[1].x--;
corners[1].y--;
}
return TRUE;
}
/* PATH_AddFlatBezier
*
*/
static BOOL PATH_AddFlatBezier(GdiPath *pPath, POINT *pt, BOOL closed)
{
......
......@@ -51,7 +51,7 @@ extern BOOL PATH_Rectangle(struct tagDC *dc, INT x1, INT y1,
extern BOOL PATH_Ellipse(struct tagDC *dc, INT x1, INT y1,
INT x2, INT y2);
extern BOOL PATH_Arc(struct tagDC *dc, INT x1, INT y1, INT x2, INT y2,
INT xStart, INT yStart, INT xEnd, INT yEnd);
INT xStart, INT yStart, INT xEnd, INT yEnd, INT lines);
extern BOOL PATH_PolyBezierTo(struct tagDC *dc, const POINT *pt, DWORD cbCount);
extern BOOL PATH_PolyBezier(struct tagDC *dc, const POINT *pt, DWORD cbCount);
extern BOOL PATH_PolylineTo(struct tagDC *dc, const POINT *pt, DWORD cbCount);
......@@ -61,6 +61,9 @@ extern BOOL PATH_PolyPolyline(struct tagDC *dc, const POINT *pt, const DWORD *co
DWORD polylines);
extern BOOL PATH_PolyPolygon(struct tagDC *dc, const POINT *pt, const INT *counts,
UINT polygons);
extern BOOL PATH_RoundRect(struct tagDC *dc, INT x1, INT y1, INT x2, INT y2, INT ell_width,
INT ell_height);
extern BOOL PATH_AddEntry(GdiPath *pPath, const POINT *pPoint, BYTE flags);
#endif /* __WINE_PATH_H */
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