• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
36 class 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 
44 public:
45 	GraphicsPath(FillMode fillMode = FillModeAlternate):
nativePath(NULL)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):
nativePath(NULL)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):
nativePath(NULL)59 			nativePath(NULL), lastStatus(Ok)
60 	{
61 		lastStatus = DllExports::GdipCreatePath2I(
62 				points, types, count, fillMode, &nativePath);
63 	}
~GraphicsPath()64 	~GraphicsPath()
65 	{
66 		DllExports::GdipDeletePath(nativePath);
67 	}
Clone()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 
AddArc(REAL x,REAL y,REAL width,REAL height,REAL startAngle,REAL sweepAngle)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 	}
AddArc(INT x,INT y,INT width,INT height,REAL startAngle,REAL sweepAngle)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 	}
AddArc(const RectF & rect,REAL startAngle,REAL sweepAngle)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 	}
AddArc(const Rect & rect,REAL startAngle,REAL sweepAngle)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 	}
AddBezier(REAL x1,REAL y1,REAL x2,REAL y2,REAL x3,REAL y3,REAL x4,REAL y4)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 	}
AddBezier(INT x1,INT y1,INT x2,INT y2,INT x3,INT y3,INT x4,INT y4)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 	}
AddBezier(const PointF & pt1,const PointF & pt2,const PointF & pt3,const PointF & pt4)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 	}
AddBezier(const Point & pt1,const Point & pt2,const Point & pt3,const Point & pt4)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 	}
AddBeziers(const PointF * points,INT count)135 	Status AddBeziers(const PointF *points, INT count)
136 	{
137 		return updateStatus(DllExports::GdipAddPathBeziers(
138 				nativePath, points, count));
139 	}
AddBeziers(const Point * points,INT count)140 	Status AddBeziers(const Point *points, INT count)
141 	{
142 		return updateStatus(DllExports::GdipAddPathBeziersI(
143 				nativePath, points, count));
144 	}
AddClosedCurve(const PointF * points,INT count)145 	Status AddClosedCurve(const PointF *points, INT count)
146 	{
147 		return updateStatus(DllExports::GdipAddPathClosedCurve(
148 				nativePath, points, count));
149 	}
AddClosedCurve(const Point * points,INT count)150 	Status AddClosedCurve(const Point *points, INT count)
151 	{
152 		return updateStatus(DllExports::GdipAddPathClosedCurveI(
153 				nativePath, points, count));
154 	}
AddClosedCurve(const PointF * points,INT count,REAL tension)155 	Status AddClosedCurve(const PointF *points, INT count, REAL tension)
156 	{
157 		return updateStatus(DllExports::GdipAddPathClosedCurve2(
158 				nativePath, points, count, tension));
159 	}
AddClosedCurve(const Point * points,INT count,REAL tension)160 	Status AddClosedCurve(const Point *points, INT count, REAL tension)
161 	{
162 		return updateStatus(DllExports::GdipAddPathClosedCurve2I(
163 				nativePath, points, count, tension));
164 	}
AddCurve(const PointF * points,INT count)165 	Status AddCurve(const PointF *points, INT count)
166 	{
167 		return updateStatus(DllExports::GdipAddPathCurve(
168 				nativePath, points, count));
169 	}
AddCurve(const Point * points,INT count)170 	Status AddCurve(const Point *points, INT count)
171 	{
172 		return updateStatus(DllExports::GdipAddPathCurveI(
173 				nativePath, points, count));
174 	}
AddCurve(const PointF * points,INT count,REAL tension)175 	Status AddCurve(const PointF *points, INT count, REAL tension)
176 	{
177 		return updateStatus(DllExports::GdipAddPathCurve2(
178 				nativePath, points, count, tension));
179 	}
AddCurve(const Point * points,INT count,REAL tension)180 	Status AddCurve(const Point *points, INT count, REAL tension)
181 	{
182 		return updateStatus(DllExports::GdipAddPathCurve2I(
183 				nativePath, points, count, tension));
184 	}
AddCurve(const PointF * points,INT count,INT offset,INT numberOfSegments,REAL tension)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 	}
AddCurve(const Point * points,INT count,INT offset,INT numberOfSegments,REAL tension)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 	}
AddEllipse(REAL x,REAL y,REAL width,REAL height)199 	Status AddEllipse(REAL x, REAL y, REAL width, REAL height)
200 	{
201 		return updateStatus(DllExports::GdipAddPathEllipse(nativePath,
202 				x, y, width, height));
203 	}
AddEllipse(INT x,INT y,INT width,INT height)204 	Status AddEllipse(INT x, INT y, INT width, INT height)
205 	{
206 		return updateStatus(DllExports::GdipAddPathEllipseI(nativePath,
207 				x, y, width, height));
208 	}
AddEllipse(const RectF & rect)209 	Status AddEllipse(const RectF& rect)
210 	{
211 		return updateStatus(DllExports::GdipAddPathEllipse(nativePath,
212 				rect.X, rect.Y, rect.Width, rect.Height));
213 	}
AddEllipse(const Rect & rect)214 	Status AddEllipse(const Rect& rect)
215 	{
216 		return updateStatus(DllExports::GdipAddPathEllipseI(nativePath,
217 				rect.X, rect.Y, rect.Width, rect.Height));
218 	}
AddLine(REAL x1,REAL y1,REAL x2,REAL y2)219 	Status AddLine(REAL x1, REAL y1, REAL x2, REAL y2)
220 	{
221 		return updateStatus(DllExports::GdipAddPathLine(nativePath,
222 				x1, y1, x2, y2));
223 	}
AddLine(INT x1,INT y1,INT x2,INT y2)224 	Status AddLine(INT x1, INT y1, INT x2, INT y2)
225 	{
226 		return updateStatus(DllExports::GdipAddPathLineI(nativePath,
227 				x1, y1, x2, y2));
228 	}
AddLine(const PointF & pt1,const PointF & pt2)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 	}
AddLine(const Point & pt1,const Point & pt2)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 	}
AddLines(const PointF * points,INT count)239 	Status AddLines(const PointF *points, INT count)
240 	{
241 		return updateStatus(DllExports::GdipAddPathLine2(nativePath,
242 				points, count));
243 	}
AddLines(const Point * points,INT count)244 	Status AddLines(const Point *points, INT count)
245 	{
246 		return updateStatus(DllExports::GdipAddPathLine2I(nativePath,
247 				points, count));
248 	}
AddPath(const GraphicsPath * addingPath,BOOL connect)249 	Status AddPath(const GraphicsPath *addingPath, BOOL connect)
250 	{
251 		return updateStatus(DllExports::GdipAddPathPath(nativePath,
252 				addingPath ? addingPath->nativePath : NULL,
253 				connect));
254 	}
AddPie(REAL x,REAL y,REAL width,REAL height,REAL startAngle,REAL sweepAngle)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 	}
AddPie(INT x,INT y,INT width,INT height,REAL startAngle,REAL sweepAngle)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 	}
AddPie(const RectF & rect,REAL startAngle,REAL sweepAngle)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 	}
AddPie(const Rect & rect,REAL startAngle,REAL sweepAngle)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 	}
AddPolygon(const PointF * points,INT count)279 	Status AddPolygon(const PointF *points, INT count)
280 	{
281 		return updateStatus(DllExports::GdipAddPathPolygon(nativePath,
282 				points, count));
283 	}
AddPolygon(const Point * points,INT count)284 	Status AddPolygon(const Point *points, INT count)
285 	{
286 		return updateStatus(DllExports::GdipAddPathPolygonI(nativePath,
287 				points, count));
288 	}
AddRectangle(const RectF & rect)289 	Status AddRectangle(const RectF& rect)
290 	{
291 		return updateStatus(DllExports::GdipAddPathRectangle(nativePath,
292 				rect.X, rect.Y, rect.Width, rect.Height));
293 	}
AddRectangle(const Rect & rect)294 	Status AddRectangle(const Rect& rect)
295 	{
296 		return updateStatus(DllExports::GdipAddPathRectangleI(
297 				nativePath,
298 				rect.X, rect.Y, rect.Width, rect.Height));
299 	}
AddRectangles(const RectF * rects,INT count)300 	Status AddRectangles(const RectF *rects, INT count)
301 	{
302 		return updateStatus(DllExports::GdipAddPathRectangles(
303 				nativePath, rects, count));
304 	}
AddRectangles(const Rect * rects,INT count)305 	Status AddRectangles(const Rect *rects, INT count)
306 	{
307 		return updateStatus(DllExports::GdipAddPathRectanglesI(
308 				nativePath, rects, count));
309 	}
AddString(const WCHAR * string,INT length,const FontFamily * family,INT style,REAL emSize,const PointF & origin,const StringFormat * format)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 	}
AddString(const WCHAR * string,INT length,const FontFamily * family,INT style,REAL emSize,const Point & origin,const StringFormat * format)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 	}
AddString(const WCHAR * string,INT length,const FontFamily * family,INT style,REAL emSize,const RectF & layoutRect,const StringFormat * format)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 	}
AddString(const WCHAR * string,INT length,const FontFamily * family,INT style,REAL emSize,const Rect & layoutRect,const StringFormat * format)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 	}
ClearMarkers()352 	Status ClearMarkers()
353 	{
354 		return updateStatus(DllExports::GdipClearPathMarkers(
355 				nativePath));
356 	}
CloseAllFigures()357 	Status CloseAllFigures()
358 	{
359 		return updateStatus(DllExports::GdipClosePathFigures(
360 				nativePath));
361 	}
CloseFigure()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 	}
GetFillMode()390 	FillMode GetFillMode() const
391 	{
392 		FillMode result = FillModeAlternate;
393 		updateStatus(DllExports::GdipGetPathFillMode(nativePath,
394 				&result));
395 		return result;
396 	}
GetLastPoint(PointF * lastPoint)397 	Status GetLastPoint(PointF *lastPoint) const
398 	{
399 		return updateStatus(DllExports::GdipGetPathLastPoint(
400 				nativePath, lastPoint));
401 	}
GetLastStatus()402 	Status GetLastStatus() const
403 	{
404 		Status result = lastStatus;
405 		lastStatus = Ok;
406 		return result;
407 	}
GetPathData(PathData * pathData)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 	}
GetPathPoints(PointF * points,INT count)425 	Status GetPathPoints(PointF *points, INT count) const
426 	{
427 		return updateStatus(DllExports::GdipGetPathPoints(nativePath,
428 				points, count));
429 	}
GetPathPoints(Point * points,INT count)430 	Status GetPathPoints(Point *points, INT count) const
431 	{
432 		return updateStatus(DllExports::GdipGetPathPointsI(nativePath,
433 				points, count));
434 	}
GetPathTypes(BYTE * types,INT count)435 	Status GetPathTypes(BYTE *types, INT count) const
436 	{
437 		return updateStatus(DllExports::GdipGetPathTypes(nativePath,
438 				types, count));
439 	}
GetPointCount()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 	}
Reset()467 	Status Reset()
468 	{
469 		return updateStatus(DllExports::GdipResetPath(nativePath));
470 	}
Reverse()471 	Status Reverse()
472 	{
473 		return updateStatus(DllExports::GdipReversePath(nativePath));
474 	}
SetFillMode(FillMode fillMode)475 	Status SetFillMode(FillMode fillMode)
476 	{
477 		return updateStatus(DllExports::GdipSetPathFillMode(
478 				nativePath, fillMode));
479 	}
SetMarker()480 	Status SetMarker()
481 	{
482 		return updateStatus(DllExports::GdipSetPathMarker(nativePath));
483 	}
StartFigure()484 	Status StartFigure()
485 	{
486 		return updateStatus(DllExports::GdipStartPathFigure(
487 				nativePath));
488 	}
Transform(const Matrix * matrix)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 
516 private:
GraphicsPath(GpPath * path,Status status)517 	GraphicsPath(GpPath *path, Status status):
518 		nativePath(path), lastStatus(status) {}
519 	GraphicsPath(const GraphicsPath&);
520 	GraphicsPath& operator=(const GraphicsPath&);
521 
updateStatus(Status newStatus)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 
532 class GraphicsPathIterator: public GdiplusBase
533 {
534 public:
GraphicsPathIterator(GraphicsPath * path)535 	GraphicsPathIterator(GraphicsPath *path):
536 		nativePathIterator(NULL), lastStatus(Ok)
537 	{
538 		lastStatus = DllExports::GdipCreatePathIter(
539 				&nativePathIterator,
540 				path ? path->nativePath : NULL);
541 	}
~GraphicsPathIterator()542 	~GraphicsPathIterator()
543 	{
544 		DllExports::GdipDeletePathIter(nativePathIterator);
545 	}
546 
CopyData(PointF * points,BYTE * types,INT startIndex,INT endIndex)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 	}
Enumerate(PointF * points,BYTE * types,INT count)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 	}
GetCount()563 	INT GetCount() const
564 	{
565 		INT result = 0;
566 		updateStatus(DllExports::GdipPathIterGetCount(
567 				nativePathIterator, &result));
568 		return result;
569 	}
GetLastStatus()570 	Status GetLastStatus() const
571 	{
572 		Status result = lastStatus;
573 		lastStatus = Ok;
574 		return result;
575 	}
GetSubpathCount()576 	INT GetSubpathCount() const
577 	{
578 		INT result = 0;
579 		updateStatus(DllExports::GdipPathIterGetSubpathCount(
580 				nativePathIterator, &result));
581 		return result;
582 	}
HasCurve()583 	BOOL HasCurve() const
584 	{
585 		BOOL result = FALSE;
586 		updateStatus(DllExports::GdipPathIterHasCurve(
587 				nativePathIterator, &result));
588 		return result;
589 	}
NextMarker(INT * startIndex,INT * endIndex)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 	}
NextMarker(GraphicsPath * path)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 	}
NextPathType(BYTE * pathType,INT * startIndex,INT * endIndex)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 	}
NextSubpath(INT * startIndex,INT * endIndex,BOOL * isClosed)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 	}
NextSubpath(GraphicsPath * path,BOOL * isClosed)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 	}
Rewind()630 	VOID Rewind()
631 	{
632 		updateStatus(DllExports::GdipPathIterRewind(
633 				nativePathIterator));
634 	}
635 
636 private:
GraphicsPathIterator(GpPathIterator * pathIterator,Status status)637 	GraphicsPathIterator(GpPathIterator *pathIterator, Status status):
638 		nativePathIterator(pathIterator), lastStatus(status) {}
639 	GraphicsPathIterator(const GraphicsPathIterator&);
640 	GraphicsPathIterator& operator=(const GraphicsPathIterator&);
641 
updateStatus(Status newStatus)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 
652 class PathGradientBrush: public Brush
653 {
654 public:
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 	}
PathGradientBrush(const GraphicsPath * path)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 	}
Clone()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 
GetBlend(REAL * blendFactors,REAL * blendPositions,INT count)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 	}
GetBlendCount()704 	INT GetBlendCount() const
705 	{
706 		INT result = 0;
707 		updateStatus(DllExports::GdipGetPathGradientBlendCount(
708 				(GpPathGradient*) nativeBrush, &result));
709 		return result;
710 	}
GetCenterColor(Color * color)711 	Status GetCenterColor(Color *color) const
712 	{
713 		return updateStatus(DllExports::GdipGetPathGradientCenterColor(
714 				(GpPathGradient*) nativeBrush,
715 				color ? &color->Value : NULL));
716 	}
GetCenterPoint(PointF * point)717 	Status GetCenterPoint(PointF *point) const
718 	{
719 		return updateStatus(DllExports::GdipGetPathGradientCenterPoint(
720 				(GpPathGradient*) nativeBrush, point));
721 	}
GetCenterPoint(Point * point)722 	Status GetCenterPoint(Point *point) const
723 	{
724 		return updateStatus(DllExports::GdipGetPathGradientCenterPointI(
725 				(GpPathGradient*) nativeBrush, point));
726 	}
GetFocusScales(REAL * xScale,REAL * yScale)727 	Status GetFocusScales(REAL *xScale, REAL *yScale) const
728 	{
729 		return updateStatus(DllExports::GdipGetPathGradientFocusScales(
730 				(GpPathGradient*) nativeBrush, xScale, yScale));
731 	}
GetGammaCorrection()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 	//}
GetInterpolationColorCount()744 	INT GetInterpolationColorCount() const
745 	{
746 		INT result = 0;
747 		updateStatus(DllExports::GdipGetPathGradientPresetBlendCount(
748 				(GpPathGradient*) nativeBrush, &result));
749 		return result;
750 	}
GetInterpolationColors(Color * presetColors,REAL * blendPositions,INT count)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 	}
GetPointCount()771 	INT GetPointCount() const
772 	{
773 		INT result = 0;
774 		updateStatus(DllExports::GdipGetPathGradientPointCount(
775 				(GpPathGradient*) nativeBrush, &result));
776 		return result;
777 	}
GetRectangle(RectF * rect)778 	Status GetRectangle(RectF *rect) const
779 	{
780 		return updateStatus(DllExports::GdipGetPathGradientRect(
781 				(GpPathGradient*) nativeBrush, rect));
782 	}
GetRectangle(Rect * rect)783 	Status GetRectangle(Rect *rect) const
784 	{
785 		return updateStatus(DllExports::GdipGetPathGradientRectI(
786 				(GpPathGradient*) nativeBrush, rect));
787 	}
GetSurroundColorCount()788 	INT GetSurroundColorCount() const
789 	{
790 		INT result = 0;
791 		updateStatus(DllExports::GdipGetPathGradientSurroundColorCount(
792 				(GpPathGradient*) nativeBrush, &result));
793 		return result;
794 	}
GetSurroundColors(Color * colors,INT * count)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 	}
GetTransform(Matrix * matrix)814 	Status GetTransform(Matrix *matrix) const
815 	{
816 		return updateStatus(DllExports::GdipGetPathGradientTransform(
817 				(GpPathGradient*) nativeBrush,
818 				matrix ? matrix->nativeMatrix : NULL));
819 	}
GetWrapMode()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 	}
ResetTransform()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 	}
SetBlend(REAL * blendFactors,REAL * blendPositions,INT count)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 	}
SetCenterColor(const Color & color)867 	Status SetCenterColor(const Color& color)
868 	{
869 		return updateStatus(DllExports::GdipSetPathGradientCenterColor(
870 				(GpPathGradient*) nativeBrush,
871 				color.GetValue()));
872 	}
SetCenterPoint(const PointF & point)873 	Status SetCenterPoint(const PointF& point)
874 	{
875 		return updateStatus(DllExports::GdipSetPathGradientCenterPoint(
876 				(GpPathGradient*) nativeBrush, &point));
877 	}
SetCenterPoint(const Point & point)878 	Status SetCenterPoint(const Point& point)
879 	{
880 		return updateStatus(DllExports::GdipSetPathGradientCenterPointI(
881 				(GpPathGradient*) nativeBrush, &point));
882 	}
SetFocusScales(REAL xScale,REAL yScale)883 	Status SetFocusScales(REAL xScale, REAL yScale)
884 	{
885 		return updateStatus(DllExports::GdipSetPathGradientFocusScales(
886 				(GpPathGradient*) nativeBrush, xScale, yScale));
887 	}
SetGammaCorrection(BOOL useGammaCorrection)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 	//}
SetInterpolationColors(const Color * presetColors,REAL * blendPositions,INT count)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 	}
SetSurroundColors(const Color * colors,INT * count)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 	}
SetTransform(const Matrix * matrix)938 	Status SetTransform(const Matrix *matrix)
939 	{
940 		return updateStatus(DllExports::GdipSetPathGradientTransform(
941 				(GpPathGradient*) nativeBrush,
942 				matrix ? matrix->nativeMatrix : NULL));
943 	}
SetWrapMode(WrapMode wrapMode)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 
956 private:
PathGradientBrush(GpBrush * brush,Status status)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