wine/dlls/gdiplus/graphicspath.c
2007-07-12 14:48:05 +02:00

215 lines
5.3 KiB
C

/*
* Copyright (C) 2007 Google (Evan Stade)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#include <stdarg.h>
#include <math.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "wingdi.h"
#include "gdiplus.h"
#include "gdiplus_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
/* make sure path has enough space for len more points */
static BOOL lengthen_path(GpPath *path, INT len)
{
/* initial allocation */
if(path->datalen == 0){
path->datalen = len * 2;
path->pathdata.Points = GdipAlloc(path->datalen * sizeof(PointF));
if(!path->pathdata.Points) return FALSE;
path->pathdata.Types = GdipAlloc(path->datalen);
if(!path->pathdata.Types){
GdipFree(path->pathdata.Points);
return FALSE;
}
}
/* reallocation, double size of arrays */
else if(path->datalen - path->pathdata.Count < len){
while(path->datalen - path->pathdata.Count < len)
path->datalen *= 2;
path->pathdata.Points = HeapReAlloc(GetProcessHeap(), 0,
path->pathdata.Points, path->datalen * sizeof(PointF));
if(!path->pathdata.Points) return FALSE;
path->pathdata.Types = HeapReAlloc(GetProcessHeap(), 0,
path->pathdata.Types, path->datalen);
if(!path->pathdata.Types) return FALSE;
}
return TRUE;
}
GpStatus WINGDIPAPI GdipAddPathArc(GpPath *path, REAL x1, REAL y1, REAL x2,
REAL y2, REAL startAngle, REAL sweepAngle)
{
INT count, old_count, i;
if(!path)
return InvalidParameter;
count = arc2polybezier(NULL, x1, y1, x2, y2, startAngle, sweepAngle);
if(count == 0)
return Ok;
if(!lengthen_path(path, count))
return OutOfMemory;
old_count = path->pathdata.Count;
arc2polybezier(&path->pathdata.Points[old_count], x1, y1, x2, y2,
startAngle, sweepAngle);
for(i = 0; i < count; i++){
path->pathdata.Types[old_count + i] = PathPointTypeBezier;
}
path->pathdata.Types[old_count] =
(path->newfigure ? PathPointTypeStart : PathPointTypeLine);
path->newfigure = FALSE;
path->pathdata.Count += count;
return Ok;
}
GpStatus WINGDIPAPI GdipAddPathLine2(GpPath *path, GDIPCONST GpPointF *points,
INT count)
{
INT i, old_count;
if(!path || !points)
return InvalidParameter;
if(!lengthen_path(path, count))
return OutOfMemory;
old_count = path->pathdata.Count;
for(i = 0; i < count; i++){
path->pathdata.Points[old_count + i].X = points[i].X;
path->pathdata.Points[old_count + i].Y = points[i].Y;
path->pathdata.Types[old_count + i] = PathPointTypeLine;
}
if(path->newfigure){
path->pathdata.Types[old_count] = PathPointTypeStart;
path->newfigure = FALSE;
}
path->pathdata.Count += count;
return Ok;
}
GpStatus WINGDIPAPI GdipClosePathFigure(GpPath* path)
{
if(!path)
return InvalidParameter;
if(path->pathdata.Count > 0){
path->pathdata.Types[path->pathdata.Count - 1] |= PathPointTypeCloseSubpath;
path->newfigure = TRUE;
}
return Ok;
}
GpStatus WINGDIPAPI GdipClosePathFigures(GpPath* path)
{
INT i;
if(!path)
return InvalidParameter;
for(i = 1; i < path->pathdata.Count; i++){
if(path->pathdata.Types[i] == PathPointTypeStart)
path->pathdata.Types[i-1] |= PathPointTypeCloseSubpath;
}
path->newfigure = TRUE;
return Ok;
}
GpStatus WINGDIPAPI GdipCreatePath(GpFillMode fill, GpPath **path)
{
if(!path)
return InvalidParameter;
*path = GdipAlloc(sizeof(GpPath));
if(!*path) return OutOfMemory;
(*path)->fill = fill;
(*path)->newfigure = TRUE;
return Ok;
}
GpStatus WINGDIPAPI GdipDeletePath(GpPath *path)
{
if(!path)
return InvalidParameter;
GdipFree(path);
return Ok;
}
GpStatus WINGDIPAPI GdipGetPathPoints(GpPath *path, GpPointF* points, INT count)
{
if(!path)
return InvalidParameter;
if(count < path->pathdata.Count)
return InsufficientBuffer;
memcpy(points, path->pathdata.Points, path->pathdata.Count * sizeof(GpPointF));
return Ok;
}
GpStatus WINGDIPAPI GdipGetPathTypes(GpPath *path, BYTE* types, INT count)
{
if(!path)
return InvalidParameter;
if(count < path->pathdata.Count)
return InsufficientBuffer;
memcpy(types, path->pathdata.Types, path->pathdata.Count);
return Ok;
}
GpStatus WINGDIPAPI GdipGetPointCount(GpPath *path, INT *count)
{
if(!path)
return InvalidParameter;
*count = path->pathdata.Count;
return Ok;
}