path.c
来自「一个类似windows」· C语言 代码 · 共 1,307 行 · 第 1/3 页
C
1,307 行
/* Start a new stroke */
pPath->newStroke = TRUE;
return TRUE;
}
/* PATH_LineTo
*
* Should be called when a LineTo is performed on a DC that has an
* open path. This adds a PT_LINETO entry to the path (and possibly
* a PT_MOVETO entry, if this is the first LineTo in a stroke).
* Returns TRUE if successful, else FALSE.
*/
BOOL
FASTCALL
PATH_LineTo ( PDC dc, INT x, INT y )
{
GdiPath *pPath;
POINT point, pointCurPos;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
return FALSE;
/* Convert point to device coordinates */
point.x=x;
point.y=y;
CoordLPtoDP ( dc, &point );
/* Add a PT_MOVETO if necessary */
if ( pPath->newStroke )
{
pPath->newStroke = FALSE;
IntGetCurrentPositionEx ( dc, &pointCurPos );
CoordLPtoDP ( dc, &pointCurPos );
if ( !PATH_AddEntry(pPath, &pointCurPos, PT_MOVETO) )
return FALSE;
}
/* Add a PT_LINETO entry */
return PATH_AddEntry(pPath, &point, PT_LINETO);
}
/* PATH_Rectangle
*
* Should be called when a call to Rectangle is performed on a DC that has
* an open path. Returns TRUE if successful, else FALSE.
*/
BOOL
FASTCALL
PATH_Rectangle ( PDC dc, INT x1, INT y1, INT x2, INT y2 )
{
GdiPath *pPath;
POINT corners[2], pointTemp;
INT temp;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* 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;
IntLPtoDP ( dc, corners, 2 );
/* 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 ( IntGetGraphicsMode(dc) == GM_COMPATIBLE )
{
corners[1].x--;
corners[1].y--;
}
/* Close any previous figure */
if ( !IntCloseFigure ( dc ) )
{
/* The NtGdiCloseFigure call shouldn't have failed */
assert(FALSE);
return FALSE;
}
/* Add four points to the path */
pointTemp.x=corners[1].x;
pointTemp.y=corners[0].y;
if ( !PATH_AddEntry(pPath, &pointTemp, PT_MOVETO) )
return FALSE;
if ( !PATH_AddEntry(pPath, corners, PT_LINETO) )
return FALSE;
pointTemp.x=corners[0].x;
pointTemp.y=corners[1].y;
if ( !PATH_AddEntry(pPath, &pointTemp, PT_LINETO) )
return FALSE;
if ( !PATH_AddEntry(pPath, corners+1, PT_LINETO) )
return FALSE;
/* Close the rectangle figure */
if ( !IntCloseFigure ( dc ) )
{
/* The IntCloseFigure call shouldn't have failed */
assert(FALSE);
return FALSE;
}
return TRUE;
}
BOOL
FASTCALL
PATH_RoundRect (PDC dc, INT x1, INT y1, INT x2, INT y2, INT xradius, INT yradius)
{
UNIMPLEMENTED;
return FALSE;
}
/* PATH_Ellipse
*
* Should be called when a call to Ellipse is performed on a DC that has
* an open path. This adds four Bezier splines representing the ellipse
* to the path. Returns TRUE if successful, else FALSE.
*/
BOOL
FASTCALL
PATH_Ellipse ( PDC 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 );
}
/* 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.
*/
BOOL
FASTCALL
PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2,
INT xStart, INT yStart, INT xEnd, INT yEnd)
{
GdiPath *pPath;
double angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant=0.0;
/* Initialize angleEndQuadrant to silence gcc's warning */
double x, y;
FLOAT_POINT corners[2], pointStart, pointEnd;
BOOL start, end;
INT temp;
BOOL clockwise;
/* FIXME: This function should check for all possible error returns */
/* FIXME: Do we have to respect newStroke? */
ASSERT ( dc );
clockwise = ( IntGdiGetArcDirection(dc) == AD_CLOCKWISE );
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
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 )
return TRUE;
/* Convert points to device coordinates */
corners[0].x=(FLOAT)x1;
corners[0].y=(FLOAT)y1;
corners[1].x=(FLOAT)x2;
corners[1].y=(FLOAT)y2;
pointStart.x=(FLOAT)xStart;
pointStart.y=(FLOAT)yStart;
pointEnd.x=(FLOAT)xEnd;
pointEnd.y=(FLOAT)yEnd;
INTERNAL_LPTODP_FLOAT(dc, corners);
INTERNAL_LPTODP_FLOAT(dc, corners+1);
INTERNAL_LPTODP_FLOAT(dc, &pointStart);
INTERNAL_LPTODP_FLOAT(dc, &pointEnd);
/* 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;
}
/* Compute start and end angle */
PATH_NormalizePoint(corners, &pointStart, &x, &y);
angleStart=atan2(y, x);
PATH_NormalizePoint(corners, &pointEnd, &x, &y);
angleEnd=atan2(y, x);
/* Make sure the end angle is "on the right side" of the start angle */
if ( clockwise )
{
if ( angleEnd <= angleStart )
{
angleEnd+=2*M_PI;
assert(angleEnd>=angleStart);
}
}
else
{
if(angleEnd>=angleStart)
{
angleEnd-=2*M_PI;
assert(angleEnd<=angleStart);
}
}
/* In GM_COMPATIBLE, don't include bottom and right edges */
if ( IntGetGraphicsMode(dc) == GM_COMPATIBLE )
{
corners[1].x--;
corners[1].y--;
}
/* Add the arc to the path with one Bezier spline per quadrant that the
* arc spans */
start=TRUE;
end=FALSE;
do
{
/* Determine the start and end angles for this quadrant */
if(start)
{
angleStartQuadrant=angleStart;
if ( clockwise )
angleEndQuadrant=(floor(angleStart/M_PI_2)+1.0)*M_PI_2;
else
angleEndQuadrant=(ceil(angleStart/M_PI_2)-1.0)*M_PI_2;
}
else
{
angleStartQuadrant=angleEndQuadrant;
if ( clockwise )
angleEndQuadrant+=M_PI_2;
else
angleEndQuadrant-=M_PI_2;
}
/* Have we reached the last part of the arc? */
if ( (clockwise && angleEnd<angleEndQuadrant)
|| (!clockwise && angleEnd>angleEndQuadrant)
)
{
/* Adjust the end angle for this quadrant */
angleEndQuadrant = angleEnd;
end = TRUE;
}
/* Add the Bezier spline to the path */
PATH_DoArcPart ( pPath, corners, angleStartQuadrant, angleEndQuadrant, start );
start = FALSE;
} while(!end);
return TRUE;
}
BOOL
FASTCALL
PATH_PolyBezierTo ( PDC dc, const POINT *pts, DWORD cbPoints )
{
GdiPath *pPath;
POINT pt;
ULONG i;
ASSERT ( dc );
ASSERT ( pts );
ASSERT ( cbPoints );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
return FALSE;
/* Add a PT_MOVETO if necessary */
if ( pPath->newStroke )
{
pPath->newStroke=FALSE;
IntGetCurrentPositionEx ( dc, &pt );
CoordLPtoDP ( dc, &pt );
if ( !PATH_AddEntry(pPath, &pt, PT_MOVETO) )
return FALSE;
}
for(i = 0; i < cbPoints; i++)
{
pt = pts[i];
CoordLPtoDP ( dc, &pt );
PATH_AddEntry(pPath, &pt, PT_BEZIERTO);
}
return TRUE;
}
BOOL
FASTCALL
PATH_PolyBezier ( PDC dc, const POINT *pts, DWORD cbPoints )
{
GdiPath *pPath;
POINT pt;
ULONG i;
ASSERT ( dc );
ASSERT ( pts );
ASSERT ( cbPoints );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
return FALSE;
for ( i = 0; i < cbPoints; i++ )
{
pt = pts[i];
CoordLPtoDP ( dc, &pt );
PATH_AddEntry ( pPath, &pt, (i == 0) ? PT_MOVETO : PT_BEZIERTO );
}
return TRUE;
}
BOOL
FASTCALL
PATH_Polyline ( PDC dc, const POINT *pts, DWORD cbPoints )
{
GdiPath *pPath;
POINT pt;
ULONG i;
ASSERT ( dc );
ASSERT ( pts );
ASSERT ( cbPoints );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
return FALSE;
for ( i = 0; i < cbPoints; i++ )
{
pt = pts[i];
CoordLPtoDP ( dc, &pt );
PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO : PT_LINETO);
}
return TRUE;
}
BOOL
FASTCALL
PATH_PolylineTo ( PDC dc, const POINT *pts, DWORD cbPoints )
{
GdiPath *pPath;
POINT pt;
ULONG i;
ASSERT ( dc );
ASSERT ( pts );
ASSERT ( cbPoints );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
return FALSE;
/* Add a PT_MOVETO if necessary */
if ( pPath->newStroke )
{
pPath->newStroke = FALSE;
IntGetCurrentPositionEx ( dc, &pt );
CoordLPtoDP ( dc, &pt );
if ( !PATH_AddEntry(pPath, &pt, PT_MOVETO) )
return FALSE;
}
for(i = 0; i < cbPoints; i++)
{
pt = pts[i];
CoordLPtoDP ( dc, &pt );
PATH_AddEntry(pPath, &pt, PT_LINETO);
}
return TRUE;
}
BOOL
FASTCALL
PATH_Polygon ( PDC dc, const POINT *pts, DWORD cbPoints )
{
GdiPath *pPath;
POINT pt;
ULONG i;
ASSERT ( dc );
ASSERT ( pts );
PATH_GetPathFromDC ( dc, &pPath );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?