1/*
2 * gdipluspath.h
3 *
4 * GDI+ GraphicsPath class
5 *
6 * This file is part of the w32api package.
7 *
8 * Contributors:
9 *   Created by Markus Koenig <markus@stber-koenig.de>
10 *
11 * THIS SOFTWARE IS NOT COPYRIGHTED
12 *
13 * This source code is offered for use in the public domain. You may
14 * use, modify or distribute it freely.
15 *
16 * This code is distributed in the hope that it will be useful but
17 * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
18 * DISCLAIMED. This includes but is not limited to warranties of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 */
22
23#ifndef __GDIPLUS_PATH_H
24#define __GDIPLUS_PATH_H
25#if __GNUC__ >=3
26#pragma GCC system_header
27#endif
28
29#ifndef __cplusplus
30#error "A C++ compiler is required to include gdipluspath.h."
31#endif
32
33// Note that some methods of GraphicsPath are implemented in gdiplusimpl.h.
34// This avoids a cyclic dependency on Graphics and Pen.
35
36class GraphicsPath: public GdiplusBase
37{
38	friend class CustomLineCap;
39	friend class Graphics;
40	friend class GraphicsPathIterator;
41	friend class PathGradientBrush;
42	friend class Region;
43
44public:
45	GraphicsPath(FillMode fillMode = FillModeAlternate):
46			nativePath(NULL), lastStatus(Ok)
47	{
48		lastStatus = DllExports::GdipCreatePath(fillMode, &nativePath);
49	}
50	GraphicsPath(const PointF *points, const BYTE *types, INT count,
51			FillMode fillMode = FillModeAlternate):
52			nativePath(NULL), lastStatus(Ok)
53	{
54		lastStatus = DllExports::GdipCreatePath2(
55				points, types, count, fillMode, &nativePath);
56	}
57	GraphicsPath(const Point *points, const BYTE *types, INT count,
58			FillMode fillMode = FillModeAlternate):
59			nativePath(NULL), lastStatus(Ok)
60	{
61		lastStatus = DllExports::GdipCreatePath2I(
62				points, types, count, fillMode, &nativePath);
63	}
64	~GraphicsPath()
65	{
66		DllExports::GdipDeletePath(nativePath);
67	}
68	GraphicsPath* Clone() const
69	{
70		GpPath *clonePath = NULL;
71		Status status = updateStatus(DllExports::GdipClonePath(
72				nativePath, &clonePath));
73		if (status == Ok) {
74			GraphicsPath *result = new GraphicsPath(clonePath, lastStatus);
75			if (!result) {
76				DllExports::GdipDeletePath(clonePath);
77				lastStatus = OutOfMemory;
78			}
79			return result;
80		} else {
81			return NULL;
82		}
83	}
84
85	Status AddArc(REAL x, REAL y, REAL width, REAL height,
86			REAL startAngle, REAL sweepAngle)
87	{
88		return updateStatus(DllExports::GdipAddPathArc(nativePath,
89				x, y, width, height, startAngle, sweepAngle));
90	}
91	Status AddArc(INT x, INT y, INT width, INT height,
92			REAL startAngle, REAL sweepAngle)
93	{
94		return updateStatus(DllExports::GdipAddPathArcI(nativePath,
95				x, y, width, height, startAngle, sweepAngle));
96	}
97	Status AddArc(const RectF& rect, REAL startAngle, REAL sweepAngle)
98	{
99		return updateStatus(DllExports::GdipAddPathArc(nativePath,
100				rect.X, rect.Y, rect.Width, rect.Height,
101				startAngle, sweepAngle));
102	}
103	Status AddArc(const Rect& rect, REAL startAngle, REAL sweepAngle)
104	{
105		return updateStatus(DllExports::GdipAddPathArcI(nativePath,
106				rect.X, rect.Y, rect.Width, rect.Height,
107				startAngle, sweepAngle));
108	}
109	Status AddBezier(REAL x1, REAL y1, REAL x2, REAL y2,
110			REAL x3, REAL y3, REAL x4, REAL y4)
111	{
112		return updateStatus(DllExports::GdipAddPathBezier(nativePath,
113				x1, y1, x2, y2, x3, y3, x4, y4));
114	}
115	Status AddBezier(INT x1, INT y1, INT x2, INT y2,
116			INT x3, INT y3, INT x4, INT y4)
117	{
118		return updateStatus(DllExports::GdipAddPathBezierI(nativePath,
119				x1, y1, x2, y2, x3, y3, x4, y4));
120	}
121	Status AddBezier(const PointF& pt1, const PointF& pt2,
122			const PointF& pt3, const PointF& pt4)
123	{
124		return updateStatus(DllExports::GdipAddPathBezier(nativePath,
125				pt1.X, pt1.Y, pt2.X, pt2.Y,
126				pt3.X, pt3.Y, pt4.X, pt4.Y));
127	}
128	Status AddBezier(const Point& pt1, const Point& pt2,
129			const Point& pt3, const Point& pt4)
130	{
131		return updateStatus(DllExports::GdipAddPathBezierI(nativePath,
132				pt1.X, pt1.Y, pt2.X, pt2.Y,
133				pt3.X, pt3.Y, pt4.X, pt4.Y));
134	}
135	Status AddBeziers(const PointF *points, INT count)
136	{
137		return updateStatus(DllExports::GdipAddPathBeziers(
138				nativePath, points, count));
139	}
140	Status AddBeziers(const Point *points, INT count)
141	{
142		return updateStatus(DllExports::GdipAddPathBeziersI(
143				nativePath, points, count));
144	}
145	Status AddClosedCurve(const PointF *points, INT count)
146	{
147		return updateStatus(DllExports::GdipAddPathClosedCurve(
148				nativePath, points, count));
149	}
150	Status AddClosedCurve(const Point *points, INT count)
151	{
152		return updateStatus(DllExports::GdipAddPathClosedCurveI(
153				nativePath, points, count));
154	}
155	Status AddClosedCurve(const PointF *points, INT count, REAL tension)
156	{
157		return updateStatus(DllExports::GdipAddPathClosedCurve2(
158				nativePath, points, count, tension));
159	}
160	Status AddClosedCurve(const Point *points, INT count, REAL tension)
161	{
162		return updateStatus(DllExports::GdipAddPathClosedCurve2I(
163				nativePath, points, count, tension));
164	}
165	Status AddCurve(const PointF *points, INT count)
166	{
167		return updateStatus(DllExports::GdipAddPathCurve(
168				nativePath, points, count));
169	}
170	Status AddCurve(const Point *points, INT count)
171	{
172		return updateStatus(DllExports::GdipAddPathCurveI(
173				nativePath, points, count));
174	}
175	Status AddCurve(const PointF *points, INT count, REAL tension)
176	{
177		return updateStatus(DllExports::GdipAddPathCurve2(
178				nativePath, points, count, tension));
179	}
180	Status AddCurve(const Point *points, INT count, REAL tension)
181	{
182		return updateStatus(DllExports::GdipAddPathCurve2I(
183				nativePath, points, count, tension));
184	}
185	Status AddCurve(const PointF *points, INT count, INT offset,
186			INT numberOfSegments, REAL tension)
187	{
188		return updateStatus(DllExports::GdipAddPathCurve3(
189				nativePath, points, count,
190				offset, numberOfSegments, tension));
191	}
192	Status AddCurve(const Point *points, INT count, INT offset,
193			INT numberOfSegments, REAL tension)
194	{
195		return updateStatus(DllExports::GdipAddPathCurve3I(
196				nativePath, points, count,
197				offset, numberOfSegments, tension));
198	}
199	Status AddEllipse(REAL x, REAL y, REAL width, REAL height)
200	{
201		return updateStatus(DllExports::GdipAddPathEllipse(nativePath,
202				x, y, width, height));
203	}
204	Status AddEllipse(INT x, INT y, INT width, INT height)
205	{
206		return updateStatus(DllExports::GdipAddPathEllipseI(nativePath,
207				x, y, width, height));
208	}
209	Status AddEllipse(const RectF& rect)
210	{
211		return updateStatus(DllExports::GdipAddPathEllipse(nativePath,
212				rect.X, rect.Y, rect.Width, rect.Height));
213	}
214	Status AddEllipse(const Rect& rect)
215	{
216		return updateStatus(DllExports::GdipAddPathEllipseI(nativePath,
217				rect.X, rect.Y, rect.Width, rect.Height));
218	}
219	Status AddLine(REAL x1, REAL y1, REAL x2, REAL y2)
220	{
221		return updateStatus(DllExports::GdipAddPathLine(nativePath,
222				x1, y1, x2, y2));
223	}
224	Status AddLine(INT x1, INT y1, INT x2, INT y2)
225	{
226		return updateStatus(DllExports::GdipAddPathLineI(nativePath,
227				x1, y1, x2, y2));
228	}
229	Status AddLine(const PointF& pt1, const PointF& pt2)
230	{
231		return updateStatus(DllExports::GdipAddPathLine(nativePath,
232				pt1.X, pt1.Y, pt2.X, pt2.Y));
233	}
234	Status AddLine(const Point& pt1, const Point& pt2)
235	{
236		return updateStatus(DllExports::GdipAddPathLineI(nativePath,
237				pt1.X, pt1.Y, pt2.X, pt2.Y));
238	}
239	Status AddLines(const PointF *points, INT count)
240	{
241		return updateStatus(DllExports::GdipAddPathLine2(nativePath,
242				points, count));
243	}
244	Status AddLines(const Point *points, INT count)
245	{
246		return updateStatus(DllExports::GdipAddPathLine2I(nativePath,
247				points, count));
248	}
249	Status AddPath(const GraphicsPath *addingPath, BOOL connect)
250	{
251		return updateStatus(DllExports::GdipAddPathPath(nativePath,
252				addingPath ? addingPath->nativePath : NULL,
253				connect));
254	}
255	Status AddPie(REAL x, REAL y, REAL width, REAL height,
256			REAL startAngle, REAL sweepAngle)
257	{
258		return updateStatus(DllExports::GdipAddPathPie(nativePath,
259				x, y, width, height, startAngle, sweepAngle));
260	}
261	Status AddPie(INT x, INT y, INT width, INT height,
262			REAL startAngle, REAL sweepAngle)
263	{
264		return updateStatus(DllExports::GdipAddPathPieI(nativePath,
265				x, y, width, height, startAngle, sweepAngle));
266	}
267	Status AddPie(const RectF& rect, REAL startAngle, REAL sweepAngle)
268	{
269		return updateStatus(DllExports::GdipAddPathPie(nativePath,
270				rect.X, rect.Y, rect.Width, rect.Height,
271				startAngle, sweepAngle));
272	}
273	Status AddPie(const Rect& rect, REAL startAngle, REAL sweepAngle)
274	{
275		return updateStatus(DllExports::GdipAddPathPieI(nativePath,
276				rect.X, rect.Y, rect.Width, rect.Height,
277				startAngle, sweepAngle));
278	}
279	Status AddPolygon(const PointF *points, INT count)
280	{
281		return updateStatus(DllExports::GdipAddPathPolygon(nativePath,
282				points, count));
283	}
284	Status AddPolygon(const Point *points, INT count)
285	{
286		return updateStatus(DllExports::GdipAddPathPolygonI(nativePath,
287				points, count));
288	}
289	Status AddRectangle(const RectF& rect)
290	{
291		return updateStatus(DllExports::GdipAddPathRectangle(nativePath,
292				rect.X, rect.Y, rect.Width, rect.Height));
293	}
294	Status AddRectangle(const Rect& rect)
295	{
296		return updateStatus(DllExports::GdipAddPathRectangleI(
297				nativePath,
298				rect.X, rect.Y, rect.Width, rect.Height));
299	}
300	Status AddRectangles(const RectF *rects, INT count)
301	{
302		return updateStatus(DllExports::GdipAddPathRectangles(
303				nativePath, rects, count));
304	}
305	Status AddRectangles(const Rect *rects, INT count)
306	{
307		return updateStatus(DllExports::GdipAddPathRectanglesI(
308				nativePath, rects, count));
309	}
310	Status AddString(const WCHAR *string, INT length,
311			const FontFamily *family, INT style, REAL emSize,
312			const PointF& origin, const StringFormat *format)
313	{
314		RectF layoutRect(origin, SizeF(0.0f, 0.0f));
315		return updateStatus(DllExports::GdipAddPathString(nativePath,
316				string, length,
317				family ? family->nativeFontFamily : NULL,
318				style, emSize, &layoutRect,
319				format ? format->nativeStringFormat : NULL));
320	}
321	Status AddString(const WCHAR *string, INT length,
322			const FontFamily *family, INT style, REAL emSize,
323			const Point& origin, const StringFormat *format)
324	{
325		Rect layoutRect(origin, Size(0, 0));
326		return updateStatus(DllExports::GdipAddPathStringI(nativePath,
327				string, length,
328				family ? family->nativeFontFamily : NULL,
329				style, emSize, &layoutRect,
330				format ? format->nativeStringFormat : NULL));
331	}
332	Status AddString(const WCHAR *string, INT length,
333			const FontFamily *family, INT style, REAL emSize,
334			const RectF& layoutRect, const StringFormat *format)
335	{
336		return updateStatus(DllExports::GdipAddPathString(nativePath,
337				string, length,
338				family ? family->nativeFontFamily : NULL,
339				style, emSize, &layoutRect,
340				format ? format->nativeStringFormat : NULL));
341	}
342	Status AddString(const WCHAR *string, INT length,
343			const FontFamily *family, INT style, REAL emSize,
344			const Rect& layoutRect, const StringFormat *format)
345	{
346		return updateStatus(DllExports::GdipAddPathStringI(nativePath,
347				string, length,
348				family ? family->nativeFontFamily : NULL,
349				style, emSize, &layoutRect,
350				format ? format->nativeStringFormat : NULL));
351	}
352	Status ClearMarkers()
353	{
354		return updateStatus(DllExports::GdipClearPathMarkers(
355				nativePath));
356	}
357	Status CloseAllFigures()
358	{
359		return updateStatus(DllExports::GdipClosePathFigures(
360				nativePath));
361	}
362	Status CloseFigure()
363	{
364		return updateStatus(DllExports::GdipClosePathFigure(
365				nativePath));
366	}
367	Status Flatten(const Matrix *matrix = NULL,
368			REAL flatness = FlatnessDefault)
369	{
370		return updateStatus(DllExports::GdipFlattenPath(nativePath,
371				matrix ? matrix->nativeMatrix : NULL,
372				flatness));
373	}
374	Status GetBounds(RectF *bounds, const Matrix *matrix = NULL,
375			const Pen *pen = NULL) const
376	{
377		return updateStatus(DllExports::GdipGetPathWorldBounds(
378				nativePath, bounds,
379				matrix ? matrix->nativeMatrix : NULL,
380				pen ? pen->nativePen : NULL));
381	}
382	Status GetBounds(Rect *bounds, const Matrix *matrix = NULL,
383			const Pen *pen = NULL) const
384	{
385		return updateStatus(DllExports::GdipGetPathWorldBoundsI(
386				nativePath, bounds,
387				matrix ? matrix->nativeMatrix : NULL,
388				pen ? pen->nativePen : NULL));
389	}
390	FillMode GetFillMode() const
391	{
392		FillMode result = FillModeAlternate;
393		updateStatus(DllExports::GdipGetPathFillMode(nativePath,
394				&result));
395		return result;
396	}
397	Status GetLastPoint(PointF *lastPoint) const
398	{
399		return updateStatus(DllExports::GdipGetPathLastPoint(
400				nativePath, lastPoint));
401	}
402	Status GetLastStatus() const
403	{
404		Status result = lastStatus;
405		lastStatus = Ok;
406		return result;
407	}
408	Status GetPathData(PathData *pathData) const
409	{
410		if (!pathData) return lastStatus = InvalidParameter;
411
412		Status status;
413		INT count;
414
415		status = updateStatus(DllExports::GdipGetPointCount(
416				nativePath, &count));
417		if (status != Ok) return status;
418
419		status = updateStatus(pathData->AllocateArrays(count));
420		if (status != Ok) return status;
421
422		return updateStatus(DllExports::GdipGetPathData(
423				nativePath, (GpPathData*) pathData));
424	}
425	Status GetPathPoints(PointF *points, INT count) const
426	{
427		return updateStatus(DllExports::GdipGetPathPoints(nativePath,
428				points, count));
429	}
430	Status GetPathPoints(Point *points, INT count) const
431	{
432		return updateStatus(DllExports::GdipGetPathPointsI(nativePath,
433				points, count));
434	}
435	Status GetPathTypes(BYTE *types, INT count) const
436	{
437		return updateStatus(DllExports::GdipGetPathTypes(nativePath,
438				types, count));
439	}
440	INT GetPointCount() const
441	{
442		INT result = 0;
443		updateStatus(DllExports::GdipGetPointCount(nativePath,
444				&result));
445		return result;
446	}
447	BOOL IsOutlineVisible(REAL x, REAL y, const Pen *pen,
448			const Graphics *g = NULL) const;
449	BOOL IsOutlineVisible(INT x, INT y, const Pen *pen,
450			const Graphics *g = NULL) const;
451	BOOL IsOutlineVisible(const PointF& point, const Pen *pen,
452			const Graphics *g = NULL) const;
453	BOOL IsOutlineVisible(const Point& point, const Pen *pen,
454			const Graphics *g = NULL) const;
455	BOOL IsVisible(REAL x, REAL y, const Graphics *g = NULL) const;
456	BOOL IsVisible(INT x, INT y, const Graphics *g = NULL) const;
457	BOOL IsVisible(const PointF& point, const Graphics *g = NULL) const;
458	BOOL IsVisible(const Point& point, const Graphics *g = NULL) const;
459	Status Outline(const Matrix *matrix = NULL,
460			REAL flatness = FlatnessDefault)
461	{
462		return updateStatus(DllExports::GdipWindingModeOutline(
463				nativePath,
464				matrix ? matrix->nativeMatrix : NULL,
465				flatness));
466	}
467	Status Reset()
468	{
469		return updateStatus(DllExports::GdipResetPath(nativePath));
470	}
471	Status Reverse()
472	{
473		return updateStatus(DllExports::GdipReversePath(nativePath));
474	}
475	Status SetFillMode(FillMode fillMode)
476	{
477		return updateStatus(DllExports::GdipSetPathFillMode(
478				nativePath, fillMode));
479	}
480	Status SetMarker()
481	{
482		return updateStatus(DllExports::GdipSetPathMarker(nativePath));
483	}
484	Status StartFigure()
485	{
486		return updateStatus(DllExports::GdipStartPathFigure(
487				nativePath));
488	}
489	Status Transform(const Matrix *matrix)
490	{
491		return updateStatus(DllExports::GdipTransformPath(
492				nativePath,
493				matrix ? matrix->nativeMatrix : NULL));
494	}
495	Status Warp(const PointF *destPoints, INT count, const RectF& srcRect,
496			const Matrix *matrix = NULL,
497			WarpMode warpMode = WarpModePerspective,
498			REAL flatness = FlatnessDefault)
499	{
500		return updateStatus(DllExports::GdipWarpPath(nativePath,
501				matrix ? matrix->nativeMatrix : NULL,
502				destPoints, count,
503				srcRect.X, srcRect.Y,
504				srcRect.Width, srcRect.Height,
505				warpMode, flatness));
506	}
507	Status Widen(const Pen *pen, const Matrix *matrix = NULL,
508			REAL flatness = FlatnessDefault)
509	{
510		return updateStatus(DllExports::GdipWidenPath(nativePath,
511				pen ? pen->nativePen : NULL,
512				matrix ? matrix->nativeMatrix : NULL,
513				flatness));
514	}
515
516private:
517	GraphicsPath(GpPath *path, Status status):
518		nativePath(path), lastStatus(status) {}
519	GraphicsPath(const GraphicsPath&);
520	GraphicsPath& operator=(const GraphicsPath&);
521
522	Status updateStatus(Status newStatus) const
523	{
524		if (newStatus != Ok) lastStatus = newStatus;
525		return newStatus;
526	}
527
528	GpPath *nativePath;
529	mutable Status lastStatus;
530};
531
532class GraphicsPathIterator: public GdiplusBase
533{
534public:
535	GraphicsPathIterator(GraphicsPath *path):
536		nativePathIterator(NULL), lastStatus(Ok)
537	{
538		lastStatus = DllExports::GdipCreatePathIter(
539				&nativePathIterator,
540				path ? path->nativePath : NULL);
541	}
542	~GraphicsPathIterator()
543	{
544		DllExports::GdipDeletePathIter(nativePathIterator);
545	}
546
547	INT CopyData(PointF *points, BYTE *types, INT startIndex, INT endIndex)
548	{
549		INT result = 0;
550		updateStatus(DllExports::GdipPathIterCopyData(
551				nativePathIterator, &result,
552				points, types, startIndex, endIndex));
553		return result;
554	}
555	INT Enumerate(PointF *points, BYTE *types, INT count)
556	{
557		INT result = 0;
558		updateStatus(DllExports::GdipPathIterEnumerate(
559				nativePathIterator, &result,
560				points, types, count));
561		return result;
562	}
563	INT GetCount() const
564	{
565		INT result = 0;
566		updateStatus(DllExports::GdipPathIterGetCount(
567				nativePathIterator, &result));
568		return result;
569	}
570	Status GetLastStatus() const
571	{
572		Status result = lastStatus;
573		lastStatus = Ok;
574		return result;
575	}
576	INT GetSubpathCount() const
577	{
578		INT result = 0;
579		updateStatus(DllExports::GdipPathIterGetSubpathCount(
580				nativePathIterator, &result));
581		return result;
582	}
583	BOOL HasCurve() const
584	{
585		BOOL result = FALSE;
586		updateStatus(DllExports::GdipPathIterHasCurve(
587				nativePathIterator, &result));
588		return result;
589	}
590	INT NextMarker(INT *startIndex, INT *endIndex)
591	{
592		INT result = 0;
593		updateStatus(DllExports::GdipPathIterNextMarker(
594				nativePathIterator, &result,
595				startIndex, endIndex));
596		return result;
597	}
598	INT NextMarker(GraphicsPath *path)
599	{
600		INT result = 0;
601		updateStatus(DllExports::GdipPathIterNextMarkerPath(
602				nativePathIterator, &result,
603				path ? path->nativePath : NULL));
604		return result;
605	}
606	INT NextPathType(BYTE *pathType, INT *startIndex, INT *endIndex)
607	{
608		INT result = 0;
609		updateStatus(DllExports::GdipPathIterNextPathType(
610				nativePathIterator, &result,
611				pathType, startIndex, endIndex));
612		return result;
613	}
614	INT NextSubpath(INT *startIndex, INT *endIndex, BOOL *isClosed)
615	{
616		INT result = 0;
617		updateStatus(DllExports::GdipPathIterNextSubpath(
618				nativePathIterator, &result,
619				startIndex, endIndex, isClosed));
620		return result;
621	}
622	INT NextSubpath(GraphicsPath *path, BOOL *isClosed)
623	{
624		INT result = 0;
625		updateStatus(DllExports::GdipPathIterNextSubpathPath(
626				nativePathIterator, &result,
627				path ? path->nativePath : NULL, isClosed));
628		return result;
629	}
630	VOID Rewind()
631	{
632		updateStatus(DllExports::GdipPathIterRewind(
633				nativePathIterator));
634	}
635
636private:
637	GraphicsPathIterator(GpPathIterator *pathIterator, Status status):
638		nativePathIterator(pathIterator), lastStatus(status) {}
639	GraphicsPathIterator(const GraphicsPathIterator&);
640	GraphicsPathIterator& operator=(const GraphicsPathIterator&);
641
642	Status updateStatus(Status newStatus) const
643	{
644		if (newStatus != Ok) lastStatus = newStatus;
645		return newStatus;
646	}
647
648	GpPathIterator *nativePathIterator;
649	mutable Status lastStatus;
650};
651
652class PathGradientBrush: public Brush
653{
654public:
655	PathGradientBrush(const PointF *points, INT count,
656			WrapMode wrapMode = WrapModeClamp)
657	{
658		GpPathGradient *nativePathGradient = NULL;
659		lastStatus = DllExports::GdipCreatePathGradient(
660				points, count, wrapMode, &nativePathGradient);
661		nativeBrush = nativePathGradient;
662	}
663	PathGradientBrush(const Point *points, INT count,
664			WrapMode wrapMode = WrapModeClamp)
665	{
666		GpPathGradient *nativePathGradient = NULL;
667		lastStatus = DllExports::GdipCreatePathGradientI(
668				points, count, wrapMode, &nativePathGradient);
669		nativeBrush = nativePathGradient;
670	}
671	PathGradientBrush(const GraphicsPath *path)
672	{
673		GpPathGradient *nativePathGradient = NULL;
674		lastStatus = DllExports::GdipCreatePathGradientFromPath(
675				path ? path->nativePath : NULL,
676				&nativePathGradient);
677		nativeBrush = nativePathGradient;
678	}
679	virtual PathGradientBrush *Clone() const
680	{
681		GpBrush *cloneBrush = NULL;
682		Status status = updateStatus(DllExports::GdipCloneBrush(
683				nativeBrush, &cloneBrush));
684		if (status == Ok) {
685			PathGradientBrush *result =
686				new PathGradientBrush(cloneBrush, lastStatus);
687			if (!result) {
688				DllExports::GdipDeleteBrush(cloneBrush);
689				updateStatus(OutOfMemory);
690			}
691			return result;
692		} else {
693			return NULL;
694		}
695	}
696
697	Status GetBlend(REAL *blendFactors, REAL *blendPositions,
698			INT count) const
699	{
700		return updateStatus(DllExports::GdipGetPathGradientBlend(
701				(GpPathGradient*) nativeBrush,
702				blendFactors, blendPositions, count));
703	}
704	INT GetBlendCount() const
705	{
706		INT result = 0;
707		updateStatus(DllExports::GdipGetPathGradientBlendCount(
708				(GpPathGradient*) nativeBrush, &result));
709		return result;
710	}
711	Status GetCenterColor(Color *color) const
712	{
713		return updateStatus(DllExports::GdipGetPathGradientCenterColor(
714				(GpPathGradient*) nativeBrush,
715				color ? &color->Value : NULL));
716	}
717	Status GetCenterPoint(PointF *point) const
718	{
719		return updateStatus(DllExports::GdipGetPathGradientCenterPoint(
720				(GpPathGradient*) nativeBrush, point));
721	}
722	Status GetCenterPoint(Point *point) const
723	{
724		return updateStatus(DllExports::GdipGetPathGradientCenterPointI(
725				(GpPathGradient*) nativeBrush, point));
726	}
727	Status GetFocusScales(REAL *xScale, REAL *yScale) const
728	{
729		return updateStatus(DllExports::GdipGetPathGradientFocusScales(
730				(GpPathGradient*) nativeBrush, xScale, yScale));
731	}
732	BOOL GetGammaCorrection() const
733	{
734		BOOL result = FALSE;
735		updateStatus(DllExports::GdipGetPathGradientGammaCorrection(
736				(GpPathGradient*) nativeBrush, &result));
737		return result;
738	}
739	//Status GetGraphicsPath(GraphicsPath *path) const
740	//{
741	//	// TODO: implement PathGradientBrush::GetGraphicsPath
742	//	return updateStatus(NotImplemented);
743	//}
744	INT GetInterpolationColorCount() const
745	{
746		INT result = 0;
747		updateStatus(DllExports::GdipGetPathGradientPresetBlendCount(
748				(GpPathGradient*) nativeBrush, &result));
749		return result;
750	}
751	Status GetInterpolationColors(Color *presetColors,
752			REAL *blendPositions, INT count) const
753	{
754		if (!presetColors || count <= 0)
755			return lastStatus = InvalidParameter;
756
757		ARGB *presetArgb =
758			(ARGB*) DllExports::GdipAlloc(count * sizeof(ARGB));
759		if (!presetArgb)
760			return lastStatus = OutOfMemory;
761
762		Status status = updateStatus(DllExports::GdipGetPathGradientPresetBlend(
763				(GpPathGradient*) nativeBrush,
764				presetArgb, blendPositions, count));
765		for (INT i = 0; i < count; ++i) {
766			presetColors[i].SetValue(presetArgb[i]);
767		}
768		DllExports::GdipFree((void*) presetArgb);
769		return status;
770	}
771	INT GetPointCount() const
772	{
773		INT result = 0;
774		updateStatus(DllExports::GdipGetPathGradientPointCount(
775				(GpPathGradient*) nativeBrush, &result));
776		return result;
777	}
778	Status GetRectangle(RectF *rect) const
779	{
780		return updateStatus(DllExports::GdipGetPathGradientRect(
781				(GpPathGradient*) nativeBrush, rect));
782	}
783	Status GetRectangle(Rect *rect) const
784	{
785		return updateStatus(DllExports::GdipGetPathGradientRectI(
786				(GpPathGradient*) nativeBrush, rect));
787	}
788	INT GetSurroundColorCount() const
789	{
790		INT result = 0;
791		updateStatus(DllExports::GdipGetPathGradientSurroundColorCount(
792				(GpPathGradient*) nativeBrush, &result));
793		return result;
794	}
795	Status GetSurroundColors(Color *colors, INT *count)
796	{
797		if (!colors || !count || *count <= 0)
798			return lastStatus = InvalidParameter;
799
800		ARGB *colorsArgb =
801			(ARGB*) DllExports::GdipAlloc(*count * sizeof(ARGB));
802		if (!colorsArgb)
803			return lastStatus = OutOfMemory;
804
805		Status status = updateStatus(DllExports::GdipGetPathGradientSurroundColorsWithCount(
806				(GpPathGradient*) nativeBrush,
807				colorsArgb, count));
808		for (INT i = 0; i < *count; ++i) {
809			colors[i].SetValue(colorsArgb[i]);
810		}
811		DllExports::GdipFree((void*) colorsArgb);
812		return status;
813	}
814	Status GetTransform(Matrix *matrix) const
815	{
816		return updateStatus(DllExports::GdipGetPathGradientTransform(
817				(GpPathGradient*) nativeBrush,
818				matrix ? matrix->nativeMatrix : NULL));
819	}
820	WrapMode GetWrapMode() const
821	{
822		WrapMode result = WrapModeTile;
823		updateStatus(DllExports::GdipGetPathGradientWrapMode(
824				(GpPathGradient*) nativeBrush, &result));
825		return result;
826	}
827	Status MultiplyTransform(const Matrix *matrix,
828			MatrixOrder order = MatrixOrderPrepend)
829	{
830		return updateStatus(DllExports::GdipMultiplyPathGradientTransform(
831				(GpPathGradient*) nativeBrush,
832				matrix ? matrix->nativeMatrix : NULL, order));
833	}
834	Status ResetTransform()
835	{
836		return updateStatus(DllExports::GdipResetPathGradientTransform(
837				(GpPathGradient*) nativeBrush));
838	}
839	Status RotateTransform(REAL angle,
840			MatrixOrder order = MatrixOrderPrepend)
841	{
842		return updateStatus(DllExports::GdipRotatePathGradientTransform(
843				(GpPathGradient*) nativeBrush, angle, order));
844	}
845	Status ScaleTransform(REAL sx, REAL sy,
846			MatrixOrder order = MatrixOrderPrepend)
847	{
848		return updateStatus(DllExports::GdipScalePathGradientTransform(
849				(GpPathGradient*) nativeBrush, sx, sy, order));
850	}
851	Status SetBlend(REAL *blendFactors, REAL *blendPositions, INT count)
852	{
853		return updateStatus(DllExports::GdipSetPathGradientBlend(
854				(GpPathGradient*) nativeBrush,
855				blendFactors, blendPositions, count));
856	}
857	Status SetBlendBellShape(REAL focus, REAL scale = 1.0f)
858	{
859		return updateStatus(DllExports::GdipSetPathGradientSigmaBlend(
860				(GpPathGradient*) nativeBrush, focus, scale));
861	}
862	Status SetBlendTriangularShape(REAL focus, REAL scale = 1.0f)
863	{
864		return updateStatus(DllExports::GdipSetPathGradientLinearBlend(
865				(GpPathGradient*) nativeBrush, focus, scale));
866	}
867	Status SetCenterColor(const Color& color)
868	{
869		return updateStatus(DllExports::GdipSetPathGradientCenterColor(
870				(GpPathGradient*) nativeBrush,
871				color.GetValue()));
872	}
873	Status SetCenterPoint(const PointF& point)
874	{
875		return updateStatus(DllExports::GdipSetPathGradientCenterPoint(
876				(GpPathGradient*) nativeBrush, &point));
877	}
878	Status SetCenterPoint(const Point& point)
879	{
880		return updateStatus(DllExports::GdipSetPathGradientCenterPointI(
881				(GpPathGradient*) nativeBrush, &point));
882	}
883	Status SetFocusScales(REAL xScale, REAL yScale)
884	{
885		return updateStatus(DllExports::GdipSetPathGradientFocusScales(
886				(GpPathGradient*) nativeBrush, xScale, yScale));
887	}
888	Status SetGammaCorrection(BOOL useGammaCorrection)
889	{
890		return updateStatus(DllExports::GdipSetPathGradientGammaCorrection(
891				(GpPathGradient*) nativeBrush,
892				useGammaCorrection));
893	}
894	//Status SetGraphicsPath(const GraphicsPath *path)
895	//{
896	//	// TODO: implement PathGradientBrush::SetGraphicsPath
897	//	return updateStatus(NotImplemented);
898	//}
899	Status SetInterpolationColors(const Color *presetColors,
900			REAL *blendPositions, INT count)
901	{
902		if (!presetColors || count <= 0)
903			return lastStatus = InvalidParameter;
904
905		ARGB *presetArgb =
906			(ARGB*) DllExports::GdipAlloc(count * sizeof(ARGB));
907		if (!presetArgb)
908			return lastStatus = OutOfMemory;
909		for (INT i = 0; i < count; ++i) {
910			presetArgb[i] = presetColors[i].GetValue();
911		}
912
913		Status status = updateStatus(DllExports::GdipSetPathGradientPresetBlend(
914				(GpPathGradient*) nativeBrush,
915				presetArgb, blendPositions, count));
916		DllExports::GdipFree((void*) presetArgb);
917		return status;
918	}
919	Status SetSurroundColors(const Color *colors, INT *count)
920	{
921		if (!colors || !count || *count <= 0)
922			return lastStatus = InvalidParameter;
923
924		ARGB *colorsArgb =
925			(ARGB*) DllExports::GdipAlloc(*count * sizeof(ARGB));
926		if (!colorsArgb)
927			return lastStatus = OutOfMemory;
928		for (INT i = 0; i < *count; ++i) {
929			colorsArgb[i] = colors[i].GetValue();
930		}
931
932		Status status = updateStatus(DllExports::GdipSetPathGradientSurroundColorsWithCount(
933				(GpPathGradient*) nativeBrush,
934				colorsArgb, count));
935		DllExports::GdipFree((void*) colorsArgb);
936		return status;
937	}
938	Status SetTransform(const Matrix *matrix)
939	{
940		return updateStatus(DllExports::GdipSetPathGradientTransform(
941				(GpPathGradient*) nativeBrush,
942				matrix ? matrix->nativeMatrix : NULL));
943	}
944	Status SetWrapMode(WrapMode wrapMode)
945	{
946		return updateStatus(DllExports::GdipSetPathGradientWrapMode(
947				(GpPathGradient*) nativeBrush, wrapMode));
948	}
949	Status TranslateTransform(REAL dx, REAL dy,
950			MatrixOrder order = MatrixOrderPrepend)
951	{
952		return updateStatus(DllExports::GdipTranslatePathGradientTransform(
953				(GpPathGradient*) nativeBrush, dx, dy, order));
954	}
955
956private:
957	PathGradientBrush(GpBrush *brush, Status status): Brush(brush, status) {}
958	PathGradientBrush(const PathGradientBrush&);
959	PathGradientBrush& operator=(const PathGradientBrush&);
960};
961
962
963
964#endif /* __GDIPLUS_PATH_H */
965