Home | History | Annotate | Download | only in gdiplus
      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 (at) 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):
     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 
    516 private:
    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 
    532 class GraphicsPathIterator: public GdiplusBase
    533 {
    534 public:
    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 
    636 private:
    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 
    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 	}
    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 
    956 private:
    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