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