1/**************************************************************************\
2*
3* Copyright (c) 1998-2000, Microsoft Corp.  All Rights Reserved.
4*
5* Module Name:
6*
7*   GdiplusPath.h
8*
9* Abstract:
10*
11*   Path related declarations
12*
13\**************************************************************************/
14
15#ifndef _GDIPLUSPATH_H
16#define _GDIPLUSPATH_H
17
18class GraphicsPath : public GdiplusBase
19{
20public:
21    friend class Graphics;
22    friend class Region;
23    friend class PathGradientBrush;
24    friend class GraphicsPathIterator;
25    friend class CustomLineCap;
26
27    // Path constructors
28
29    GraphicsPath(IN FillMode fillMode = FillModeAlternate)
30    {
31        nativePath = NULL;
32        lastResult = DllExports::GdipCreatePath(fillMode, &nativePath);
33    }
34
35    GraphicsPath(IN const PointF* points,
36                 IN const BYTE* types,
37                 IN INT count,
38                 IN FillMode fillMode = FillModeAlternate)
39    {
40        nativePath = NULL;
41        lastResult = DllExports::GdipCreatePath2(points,
42                                                 types,
43                                                 count,
44                                                 fillMode,
45                                                 &nativePath);
46    }
47
48    GraphicsPath(IN const Point* points,
49                 IN const BYTE* types,
50                 IN INT count,
51                 IN FillMode fillMode = FillModeAlternate)
52    {
53        nativePath = NULL;
54        lastResult = DllExports::GdipCreatePath2I(points,
55                                                  types,
56                                                  count,
57                                                  fillMode,
58                                                  &nativePath);
59    }
60
61    ~GraphicsPath()
62    {
63        DllExports::GdipDeletePath(nativePath);
64    }
65
66    /**
67     * Make a copy of the current path object
68     */
69    GraphicsPath* Clone() const
70    {
71        GpPath *clonepath = NULL;
72
73        SetStatus(DllExports::GdipClonePath(nativePath, &clonepath));
74
75        return new GraphicsPath(clonepath);
76    }
77
78    /**
79     * Reset the path object to empty (and fill mode to FillModeAlternate)
80     */
81    Status Reset()
82    {
83        return SetStatus(DllExports::GdipResetPath(nativePath));
84    }
85
86    /**
87     * Get path fill mode information
88     */
89    FillMode GetFillMode() const
90    {
91        FillMode fillmode = FillModeAlternate;
92
93        SetStatus(DllExports::GdipGetPathFillMode(nativePath, &fillmode));
94
95        return fillmode;
96    }
97
98    /**
99     * Set path fill mode information
100     */
101    Status SetFillMode(IN FillMode fillmode)
102    {
103        return SetStatus(DllExports::GdipSetPathFillMode(nativePath, fillmode));
104    }
105
106    /**
107     * Set/get path data
108     */
109    Status GetPathData(OUT PathData* pathData) const
110    {
111        if (pathData == NULL)
112        {
113            return SetStatus(InvalidParameter);
114        }
115
116        INT count = GetPointCount();
117
118        if ((count <= 0) || (pathData->Count>0 && pathData->Count<count))
119        {
120            pathData->Count = 0;
121            if (pathData->Points)
122            {
123                delete pathData->Points;
124                pathData->Points = NULL;
125            }
126
127            if (pathData->Types)
128            {
129                delete pathData->Types;
130                pathData->Types = NULL;
131            }
132
133            if (count <= 0)
134            {
135                return lastResult;
136            }
137        }
138
139        if (pathData->Count == 0)
140        {
141            pathData->Points = new PointF[count];
142            if (pathData->Points == NULL)
143            {
144                return SetStatus(OutOfMemory);
145
146            }
147            pathData->Types = new byte[count];
148            if (pathData->Types == NULL)
149            {
150                delete pathData->Points;
151                pathData->Points = NULL;
152
153                return SetStatus(OutOfMemory);
154            }
155            pathData->Count = count;
156        }
157
158        return SetStatus(DllExports::GdipGetPathData(nativePath, pathData));
159    }
160
161    /**
162     * Start/end a subpath
163     */
164    Status StartFigure()
165    {
166        return SetStatus(DllExports::GdipStartPathFigure(nativePath));
167    }
168
169    Status CloseFigure()
170    {
171        return SetStatus(DllExports::GdipClosePathFigure(nativePath));
172    }
173
174    Status CloseAllFigures()
175    {
176        return SetStatus(DllExports::GdipClosePathFigures(nativePath));
177    }
178
179    Status SetMarker()
180    {
181        return SetStatus(DllExports::GdipSetPathMarker(nativePath));
182    }
183
184    Status ClearMarkers()
185    {
186        return SetStatus(DllExports::GdipClearPathMarkers(nativePath));
187    }
188
189    Status Reverse()
190    {
191        return SetStatus(DllExports::GdipReversePath(nativePath));
192    }
193
194    Status GetLastPoint(OUT PointF* lastPoint) const
195    {
196        return SetStatus(DllExports::GdipGetPathLastPoint(nativePath, lastPoint));
197    }
198
199    /**
200     * Add lines to the path object
201     */
202    // float version
203    Status AddLine(IN const PointF& pt1,
204                   IN const PointF& pt2)
205    {
206        return AddLine(pt1.X, pt1.Y, pt2.X, pt2.Y);
207    }
208
209    Status AddLine(IN REAL x1,
210                   IN REAL y1,
211                   IN REAL x2,
212                   IN REAL y2)
213    {
214        return SetStatus(DllExports::GdipAddPathLine(nativePath, x1, y1, x2, y2));
215    }
216
217    Status AddLines(IN const PointF* points,
218                    IN INT count)
219    {
220        return SetStatus(DllExports::GdipAddPathLine2(nativePath, points, count));
221    }
222
223    // integer version
224    Status AddLine(IN const Point& pt1,
225                   IN const Point& pt2)
226    {
227        return AddLine(pt1.X,
228                       pt1.Y,
229                       pt2.X,
230                       pt2.Y);
231    }
232
233    Status AddLine(IN INT x1,
234                   IN INT y1,
235                   IN INT x2,
236                   IN INT y2)
237    {
238        return SetStatus(DllExports::GdipAddPathLineI(nativePath,
239                                                     x1,
240                                                     y1,
241                                                     x2,
242                                                     y2));
243    }
244
245    Status AddLines(IN const Point* points,
246                    IN INT count)
247    {
248        return SetStatus(DllExports::GdipAddPathLine2I(nativePath,
249                                                       points,
250                                                       count));
251    }
252
253    /**
254     * Add an arc to the path object
255     */
256    // float version
257    Status AddArc(IN const RectF& rect,
258                  IN REAL startAngle,
259                  IN REAL sweepAngle)
260    {
261        return AddArc(rect.X, rect.Y, rect.Width, rect.Height,
262                      startAngle, sweepAngle);
263    }
264
265    Status AddArc(IN REAL x,
266                  IN REAL y,
267                  IN REAL width,
268                  IN REAL height,
269                  IN REAL startAngle,
270                  IN REAL sweepAngle)
271    {
272        return SetStatus(DllExports::GdipAddPathArc(nativePath, x, y, width, height,
273                                      startAngle, sweepAngle));
274    }
275
276    // integer version
277    Status AddArc(IN const Rect& rect,
278                  IN REAL startAngle,
279                  IN REAL sweepAngle)
280    {
281        return AddArc(rect.X, rect.Y, rect.Width, rect.Height,
282                      startAngle, sweepAngle);
283    }
284
285    Status AddArc(IN INT x,
286                  IN INT y,
287                  IN INT width,
288                  IN INT height,
289                  IN REAL startAngle,
290                  IN REAL sweepAngle)
291    {
292        return SetStatus(DllExports::GdipAddPathArcI(nativePath,
293                                                    x,
294                                                    y,
295                                                    width,
296                                                    height,
297                                                    startAngle,
298                                                    sweepAngle));
299    }
300
301    /**
302     * Add Bezier curves to the path object
303     */
304    // float version
305    Status AddBezier(IN const PointF& pt1,
306                     IN const PointF& pt2,
307                     IN const PointF& pt3,
308                     IN const PointF& pt4)
309    {
310        return AddBezier(pt1.X, pt1.Y, pt2.X, pt2.Y, pt3.X, pt3.Y, pt4.X,
311                         pt4.Y);
312    }
313
314    Status AddBezier(IN REAL x1,
315                     IN REAL y1,
316                     IN REAL x2,
317                     IN REAL y2,
318                     IN REAL x3,
319                     IN REAL y3,
320                     IN REAL x4,
321                     IN REAL y4)
322    {
323        return SetStatus(DllExports::GdipAddPathBezier(nativePath, x1, y1, x2, y2,
324                                     x3, y3, x4, y4));
325    }
326
327    Status AddBeziers(IN const PointF* points,
328                      IN INT count)
329    {
330        return SetStatus(DllExports::GdipAddPathBeziers(nativePath, points, count));
331    }
332
333    // integer version
334    Status AddBezier(IN const Point& pt1,
335                     IN const Point& pt2,
336                     IN const Point& pt3,
337                     IN const Point& pt4)
338    {
339       return AddBezier(pt1.X, pt1.Y, pt2.X, pt2.Y, pt3.X, pt3.Y, pt4.X,
340                        pt4.Y);
341    }
342
343    Status AddBezier(IN INT x1,
344                     IN INT y1,
345                     IN INT x2,
346                     IN INT y2,
347                     IN INT x3,
348                     IN INT y3,
349                     IN INT x4,
350                     IN INT y4)
351    {
352       return SetStatus(DllExports::GdipAddPathBezierI(nativePath,
353                                                      x1,
354                                                      y1,
355                                                      x2,
356                                                      y2,
357                                                      x3,
358                                                      y3,
359                                                      x4,
360                                                      y4));
361    }
362
363    Status AddBeziers(IN const Point* points,
364                      IN INT count)
365    {
366       return SetStatus(DllExports::GdipAddPathBeziersI(nativePath,
367                                                        points,
368                                                        count));
369    }
370
371    // float version
372    Status AddCurve(IN const PointF* points,
373                    IN INT count)
374    {
375        return SetStatus(DllExports::GdipAddPathCurve(nativePath,
376                                                      points,
377                                                      count));
378    }
379
380    Status AddCurve(IN const PointF* points,
381                    IN INT count,
382                    IN REAL tension)
383    {
384        return SetStatus(DllExports::GdipAddPathCurve2(nativePath,
385                                                       points,
386                                                       count,
387                                                       tension));
388    }
389
390    Status AddCurve(IN const PointF* points,
391                    IN INT count,
392                    IN INT offset,
393                    IN INT numberOfSegments,
394                    IN REAL tension)
395    {
396        return SetStatus(DllExports::GdipAddPathCurve3(nativePath,
397                                                       points,
398                                                       count,
399                                                       offset,
400                                                       numberOfSegments,
401                                                       tension));
402    }
403
404    // integer version
405    Status AddCurve(IN const Point* points,
406                    IN INT count)
407    {
408       return SetStatus(DllExports::GdipAddPathCurveI(nativePath,
409                                                     points,
410                                                     count));
411    }
412
413    Status AddCurve(IN const Point* points,
414                    IN INT count,
415                    IN REAL tension)
416    {
417       return SetStatus(DllExports::GdipAddPathCurve2I(nativePath,
418                                                      points,
419                                                      count,
420                                                      tension));
421    }
422
423    Status AddCurve(IN const Point* points,
424                    IN INT count,
425                    IN INT offset,
426                    IN INT numberOfSegments,
427                    IN REAL tension)
428    {
429       return SetStatus(DllExports::GdipAddPathCurve3I(nativePath,
430                                                      points,
431                                                      count,
432                                                      offset,
433                                                      numberOfSegments,
434                                                      tension));
435    }
436
437    // float version
438    Status AddClosedCurve(IN const PointF* points,
439                          IN INT count)
440    {
441        return SetStatus(DllExports::GdipAddPathClosedCurve(nativePath,
442                                                            points,
443                                                            count));
444    }
445
446    Status AddClosedCurve(IN const PointF* points,
447                          IN INT count,
448                          IN REAL tension)
449    {
450        return SetStatus(DllExports::GdipAddPathClosedCurve2(nativePath,
451                                                             points,
452                                                             count,
453                                                             tension));
454    }
455
456    // integer version
457    Status AddClosedCurve(IN const Point* points,
458                          IN INT count)
459    {
460       return SetStatus(DllExports::GdipAddPathClosedCurveI(nativePath,
461                                                            points,
462                                                            count));
463    }
464
465
466    Status AddClosedCurve(IN const Point* points,
467                          IN INT count,
468                          IN REAL tension)
469    {
470       return SetStatus(DllExports::GdipAddPathClosedCurve2I(nativePath,
471                                                             points,
472                                                             count,
473                                                             tension));
474    }
475
476
477    /**
478     * Add closed shapes to the path object
479     */
480
481    // float version
482    Status AddRectangle(IN const RectF& rect)
483    {
484        return SetStatus(DllExports::GdipAddPathRectangle(nativePath,
485                                                          rect.X,
486                                                          rect.Y,
487                                                          rect.Width,
488                                                          rect.Height));
489    }
490
491    Status AddRectangles(IN const RectF* rects,
492                         IN INT count)
493    {
494        return SetStatus(DllExports::GdipAddPathRectangles(nativePath,
495                                                           rects,
496                                                           count));
497    }
498
499    // integer version
500    Status AddRectangle(IN const Rect& rect)
501    {
502        return SetStatus(DllExports::GdipAddPathRectangleI(nativePath,
503                                                          rect.X,
504                                                          rect.Y,
505                                                          rect.Width,
506                                                          rect.Height));
507    }
508
509    Status AddRectangles(IN const Rect* rects, INT count)
510    {
511        return SetStatus(DllExports::GdipAddPathRectanglesI(nativePath,
512                                                           rects,
513                                                           count));
514    }
515
516    // float version
517    Status AddEllipse(IN const RectF& rect)
518    {
519        return AddEllipse(rect.X, rect.Y, rect.Width, rect.Height);
520    }
521
522    Status AddEllipse(IN REAL x,
523                      IN REAL y,
524                      IN REAL width,
525                      IN REAL height)
526    {
527        return SetStatus(DllExports::GdipAddPathEllipse(nativePath,
528                                                        x,
529                                                        y,
530                                                        width,
531                                                        height));
532    }
533
534    // integer version
535    Status AddEllipse(IN const Rect& rect)
536    {
537        return AddEllipse(rect.X, rect.Y, rect.Width, rect.Height);
538    }
539
540    Status AddEllipse(IN INT x,
541                      IN INT y,
542                      IN INT width,
543                      IN INT height)
544    {
545        return SetStatus(DllExports::GdipAddPathEllipseI(nativePath,
546                                                        x,
547                                                        y,
548                                                        width,
549                                                        height));
550    }
551
552    // float version
553    Status AddPie(IN const RectF& rect,
554                  IN REAL startAngle,
555                  IN REAL sweepAngle)
556    {
557        return AddPie(rect.X, rect.Y, rect.Width, rect.Height, startAngle,
558                      sweepAngle);
559    }
560
561    Status AddPie(IN REAL x,
562                  IN REAL y,
563                  IN REAL width,
564                  IN REAL height,
565                  IN REAL startAngle,
566                  IN REAL sweepAngle)
567    {
568        return SetStatus(DllExports::GdipAddPathPie(nativePath, x, y, width, height,
569                                      startAngle, sweepAngle));
570    }
571
572    // integer version
573    Status AddPie(IN const Rect& rect,
574                  IN REAL startAngle,
575                  IN REAL sweepAngle)
576    {
577        return AddPie(rect.X,
578                      rect.Y,
579                      rect.Width,
580                      rect.Height,
581                      startAngle,
582                      sweepAngle);
583    }
584
585    Status AddPie(IN INT x,
586                  IN INT y,
587                  IN INT width,
588                  IN INT height,
589                  IN REAL startAngle,
590                  IN REAL sweepAngle)
591    {
592        return SetStatus(DllExports::GdipAddPathPieI(nativePath,
593                                                    x,
594                                                    y,
595                                                    width,
596                                                    height,
597                                                    startAngle,
598                                                    sweepAngle));
599    }
600
601    // float version
602    Status AddPolygon(IN const PointF* points,
603                      IN INT count)
604    {
605        return SetStatus(DllExports::GdipAddPathPolygon(nativePath, points, count));
606    }
607
608    // integer version
609    Status AddPolygon(IN const Point* points,
610                      IN INT count)
611    {
612       return SetStatus(DllExports::GdipAddPathPolygonI(nativePath, points, count));
613    }
614
615    Status AddPath(IN const GraphicsPath* addingPath,
616                   IN BOOL connect)
617    {
618        GpPath* nativePath2 = NULL;
619        if(addingPath)
620            nativePath2 = addingPath->nativePath;
621
622        return SetStatus(DllExports::GdipAddPathPath(nativePath, nativePath2, connect));
623    }
624
625    // AddString point version
626
627    Status AddString(
628        IN const WCHAR         *string,
629        IN INT                  length,
630        IN const FontFamily    *family,
631        IN INT                  style,
632        IN REAL                 emSize,  // In world units
633        IN const PointF        &origin,
634        IN const StringFormat  *format
635    )
636    {
637        RectF rect(origin.X, origin.Y, 0.0f, 0.0f);
638
639        return SetStatus(DllExports::GdipAddPathString(
640            nativePath,
641            string,
642            length,
643            family ? family->nativeFamily : NULL,
644            style,
645            emSize,
646            &rect,
647            format ? format->nativeFormat : NULL
648        ));
649    }
650
651    // AddString rectangle version
652
653    Status AddString(
654        IN const WCHAR         *string,
655        IN INT                  length,
656        IN const FontFamily    *family,
657        IN INT                  style,
658        IN REAL                 emSize,  // In world units
659        IN const RectF         &layoutRect,
660        IN const StringFormat  *format
661    )
662    {
663        return SetStatus(DllExports::GdipAddPathString(
664            nativePath,
665            string,
666            length,
667            family ? family->nativeFamily : NULL,
668            style,
669            emSize,
670            &layoutRect,
671            format ? format->nativeFormat : NULL
672        ));
673    }
674
675    Status AddString(
676        IN const WCHAR         *string,
677        IN INT                  length,
678        IN const FontFamily    *family,
679        IN INT                  style,
680        IN REAL                 emSize,  // In world units
681        IN const Point         &origin,
682        IN const StringFormat  *format
683    )
684    {
685        Rect rect(origin.X, origin.Y, 0, 0);
686
687        return SetStatus(DllExports::GdipAddPathStringI(
688            nativePath,
689            string,
690            length,
691            family ? family->nativeFamily : NULL,
692            style,
693            emSize,
694            &rect,
695            format ? format->nativeFormat : NULL
696        ));
697    }
698
699    // AddString rectangle version
700
701    Status AddString(
702        IN const WCHAR         *string,
703        IN INT                  length,
704        IN const FontFamily    *family,
705        IN INT                  style,
706        IN REAL                 emSize,  // In world units
707        IN const Rect          &layoutRect,
708        IN const StringFormat  *format
709    )
710    {
711        return SetStatus(DllExports::GdipAddPathStringI(
712            nativePath,
713            string,
714            length,
715            family ? family->nativeFamily : NULL,
716            style,
717            emSize,
718            &layoutRect,
719            format ? format->nativeFormat : NULL
720        ));
721    }
722
723    /**
724     * Transforms the path object
725     */
726    Status Transform(IN const Matrix* matrix)
727    {
728        if(matrix)
729            return SetStatus(DllExports::GdipTransformPath(nativePath, matrix->nativeMatrix));
730        else
731            return Ok;  // No need to transform.
732    }
733
734    /**
735     * Get the bounds of the path object with the given transform.
736     * This is not always the tightest bounds.
737     *
738     * Defined in GdiplusGraphics.h.
739     */
740    Status GetBounds(OUT RectF* bounds,
741                     IN const Matrix* matrix = NULL,
742                     IN const Pen* pen = NULL) const;
743
744    // integer version (defined in GdiplusGraphics.h)
745    Status GetBounds(OUT Rect* bounds,
746                     IN const Matrix* matrix = NULL,
747                     IN const Pen* pen = NULL) const;
748
749    /**
750     * Flatten the path object
751     * Once this is called, the resultant path is made of line segments and
752     * the original path information is lost.
753     * When matrix = NULL, the identity matrix is assumed.
754     */
755    Status Flatten(IN const Matrix* matrix = NULL,
756                   IN REAL flatness = FlatnessDefault)
757    {
758        GpMatrix* nativeMatrix = NULL;
759        if(matrix)
760        {
761            nativeMatrix = matrix->nativeMatrix;
762        }
763
764        return SetStatus(DllExports::GdipFlattenPath(
765            nativePath,
766            nativeMatrix,
767            flatness
768        ));
769    }
770
771#ifdef DCR_USE_NEW_202903
772
773    Status Widen(
774        IN const Pen* pen,
775        IN const Matrix* matrix = NULL,
776        IN REAL flatness = FlatnessDefault
777    )
778    {
779        GpMatrix* nativeMatrix = NULL;
780        if(matrix)
781            nativeMatrix = matrix->nativeMatrix;
782
783        return SetStatus(DllExports::GdipWidenPath(
784            nativePath,
785            pen->nativePen,
786            nativeMatrix,
787            flatness
788        ));
789    }
790
791#else
792
793    /**
794     * Widen the path object
795     * When removeSelfIntersects is TRUE, this returns the widened path
796     * without self intersections.
797     * When it is FALSE, it returns the widened path with selfintersections.
798     * The latter is faster and is usually safficient for filling.
799     */
800    Status Widen(IN const Pen* pen,
801                 IN const Matrix* matrix = NULL,
802                 IN BOOL removeSelfIntersects = TRUE)
803    {
804        GpMatrix* nativeMatrix = NULL;
805        if(matrix)
806            nativeMatrix = matrix->nativeMatrix;
807
808        return SetStatus(DllExports::GdipWidenPathWithMinimumResolutions(nativePath, pen->nativePen,
809            0, 0, nativeMatrix, removeSelfIntersects));
810    }
811
812    /**
813     * Widen the path object
814     * This is equivalent to Widen() method except that
815     * The widths of the widened path are larger than the given
816     * minimum resolutions in x and y coordinates after the transform.
817     * This is usefull when widening a path with the limited device resolutions.
818     */
819
820    Status Widen(IN const Pen* pen,
821                 IN REAL minXres,
822                 IN REAL minYres,
823                 IN const Matrix* matrix = NULL,
824                 IN BOOL removeSelfIntersects = TRUE)
825    {
826        GpMatrix* nativeMatrix = NULL;
827        if(matrix)
828            nativeMatrix = matrix->nativeMatrix;
829
830        return SetStatus(DllExports::GdipWidenPathWithMinimumResolutions(nativePath, pen->nativePen,
831            minXres, minYres, nativeMatrix, removeSelfIntersects));
832    }
833
834#endif // DCR_USE_NEW_202903
835
836    Status Outline(
837        IN const Matrix *matrix = NULL,
838        IN REAL flatness = FlatnessDefault
839    )
840    {
841        GpMatrix* nativeMatrix = NULL;
842        if(matrix)
843        {
844            nativeMatrix = matrix->nativeMatrix;
845        }
846
847        return SetStatus(DllExports::GdipWindingModeOutline(
848            nativePath, nativeMatrix, flatness
849        ));
850    }
851
852    /**
853     * Warp the path object
854     * Once this is called, the resultant path is made of line segments and
855     * the original path information is lost.
856     * When matrix = NULL, the identity matrix is assumed.
857     */
858    Status Warp(IN const PointF* destPoints,
859                IN INT count,
860                IN const RectF& srcRect,
861                IN const Matrix* matrix = NULL,
862                IN WarpMode warpMode = WarpModePerspective,
863                IN REAL flatness = FlatnessDefault)
864    {
865        GpMatrix* nativeMatrix = NULL;
866        if(matrix)
867            nativeMatrix = matrix->nativeMatrix;
868
869        return SetStatus(DllExports::GdipWarpPath(
870                                        nativePath,
871                                        nativeMatrix,
872                                        destPoints,
873                                        count,
874                                        srcRect.X,
875                                        srcRect.Y,
876                                        srcRect.Width,
877                                        srcRect.Height,
878                                        warpMode,
879                                        flatness));
880    }
881
882    /**
883     * Return the number of points in the current path
884     */
885    INT GetPointCount() const
886    {
887        INT count = 0;
888
889        SetStatus(DllExports::GdipGetPointCount(nativePath, &count));
890
891        return count;
892    }
893
894    /**
895     * Return the path point type information
896     */
897    Status GetPathTypes(OUT BYTE* types,
898                        IN INT count) const
899    {
900        return SetStatus(DllExports::GdipGetPathTypes(nativePath, types, count));
901    }
902
903    /**
904     * Return the path point coordinate information
905     * @notes Should there be PathData that contains types[] and points[]
906     *        for get & set purposes.
907     */
908    Status GetPathPoints(OUT PointF* points,
909                         IN INT count) const
910    {
911        return SetStatus(DllExports::GdipGetPathPoints(nativePath, points, count));
912    }
913
914    // integer version
915    Status GetPathPoints(OUT Point* points,
916                         IN INT count) const
917    {
918        return SetStatus(DllExports::GdipGetPathPointsI(nativePath, points, count));
919    }
920
921    Status GetLastStatus() const
922    {
923        Status lastStatus = lastResult;
924        lastResult = Ok;
925
926        return lastStatus;
927    }
928
929    /**
930     * Hit testing operations
931     *
932     * inline implementation is in gdiplusgraphics.h.
933     */
934
935    BOOL IsVisible(IN const PointF& point,
936                   IN const Graphics* g = NULL) const
937    {
938        return IsVisible(point.X, point.Y, g);
939    }
940
941    BOOL IsVisible(IN REAL x,
942                   IN REAL y,
943                   IN const Graphics* g = NULL) const;
944
945    BOOL IsVisible(IN const Point& point,
946                   IN const Graphics* g = NULL) const
947    {
948        return IsVisible(point.X, point.Y, g);
949    }
950
951    BOOL IsVisible(IN INT x,
952                   IN INT y,
953                   IN const Graphics* g = NULL) const;
954
955    BOOL IsOutlineVisible(IN const PointF& point,
956                          IN const Pen* pen,
957                          IN const Graphics* g = NULL) const
958    {
959        return IsOutlineVisible(point.X, point.Y, pen, g);
960    }
961
962    BOOL IsOutlineVisible(IN REAL x,
963                          IN REAL y,
964                          IN const Pen* pen,
965                          IN const Graphics* g = NULL) const;
966
967    BOOL IsOutlineVisible(IN const Point& point,
968                          IN const Pen* pen,
969                          IN const Graphics* g = NULL) const
970    {
971        return IsOutlineVisible(point.X, point.Y, pen, g);
972    }
973
974    BOOL IsOutlineVisible(IN INT x,
975                          IN INT y,
976                          IN const Pen* pen,
977                          IN const Graphics* g = NULL) const;
978
979protected:
980
981    GraphicsPath(const GraphicsPath& path)
982    {
983        GpPath *clonepath = NULL;
984        SetStatus(DllExports::GdipClonePath(path.nativePath, &clonepath));
985        SetNativePath(clonepath);
986    }
987
988#ifdef DCR_USE_NEW_250932
989
990private:
991    GraphicsPath& operator=(const GraphicsPath &);
992protected:
993
994#else
995
996    GraphicsPath& operator=(const GraphicsPath& path)
997    {
998        path;
999        SetStatus(NotImplemented);
1000        return *this;
1001    }
1002
1003#endif
1004
1005    GraphicsPath(GpPath* nativePath)
1006    {
1007        lastResult = Ok;
1008        SetNativePath(nativePath);
1009    }
1010
1011    VOID SetNativePath(GpPath *nativePath)
1012    {
1013        this->nativePath = nativePath;
1014    }
1015
1016    Status SetStatus(Status status) const
1017    {
1018        if (status != Ok)
1019            return (lastResult = status);
1020        else
1021            return status;
1022    }
1023
1024protected:
1025    GpPath* nativePath;
1026    mutable Status lastResult;
1027};
1028
1029
1030//--------------------------------------------------------------------------
1031// GraphisPathIterator class
1032//--------------------------------------------------------------------------
1033
1034class GraphicsPathIterator : public GdiplusBase
1035{
1036public:
1037
1038    GraphicsPathIterator(IN const GraphicsPath* path)
1039    {
1040        GpPath* nativePath = NULL;
1041        if(path)
1042            nativePath = path->nativePath;
1043
1044        GpPathIterator *iter = NULL;
1045        lastResult = DllExports::GdipCreatePathIter(&iter, nativePath);
1046        SetNativeIterator(iter);
1047    }
1048
1049    ~GraphicsPathIterator()
1050    {
1051        DllExports::GdipDeletePathIter(nativeIterator);
1052    }
1053
1054
1055    INT NextSubpath(OUT INT* startIndex,
1056                    OUT INT* endIndex,
1057                    OUT BOOL* isClosed)
1058    {
1059        INT resultCount;
1060
1061        SetStatus(DllExports::GdipPathIterNextSubpath(nativeIterator,
1062            &resultCount, startIndex, endIndex, isClosed));
1063
1064        return resultCount;
1065    }
1066
1067
1068    INT NextSubpath(IN const GraphicsPath* path,
1069                    OUT BOOL* isClosed)
1070    {
1071        GpPath* nativePath = NULL;
1072
1073        INT resultCount;
1074
1075        if(path)
1076            nativePath= path->nativePath;
1077
1078        SetStatus(DllExports::GdipPathIterNextSubpathPath(nativeIterator,
1079            &resultCount, nativePath, isClosed));
1080
1081        return resultCount;
1082    }
1083
1084    INT NextPathType(OUT BYTE* pathType,
1085                     OUT INT* startIndex,
1086                     OUT INT* endIndex)
1087    {
1088        INT resultCount;
1089
1090        SetStatus(DllExports::GdipPathIterNextPathType(nativeIterator,
1091            &resultCount, pathType, startIndex, endIndex));
1092
1093        return resultCount;
1094    }
1095
1096    INT NextMarker(OUT INT* startIndex,
1097                   OUT INT* endIndex)
1098    {
1099        INT resultCount;
1100
1101        SetStatus(DllExports::GdipPathIterNextMarker(nativeIterator,
1102            &resultCount, startIndex, endIndex));
1103
1104        return resultCount;
1105    }
1106
1107
1108    INT NextMarker(IN const GraphicsPath* path)
1109    {
1110        GpPath* nativePath = NULL;
1111
1112        INT resultCount;
1113
1114        if(path)
1115            nativePath= path->nativePath;
1116
1117        SetStatus(DllExports::GdipPathIterNextMarkerPath(nativeIterator,
1118            &resultCount, nativePath));
1119
1120        return resultCount;
1121    }
1122
1123    INT GetCount() const
1124    {
1125        INT resultCount;
1126
1127        SetStatus(DllExports::GdipPathIterGetCount(nativeIterator, &resultCount));
1128
1129        return resultCount;
1130    }
1131
1132    INT GetSubpathCount() const
1133    {
1134        INT resultCount;
1135
1136        SetStatus(DllExports::GdipPathIterGetSubpathCount(nativeIterator, &resultCount));
1137
1138        return resultCount;
1139    }
1140
1141    BOOL HasCurve() const
1142    {
1143        BOOL hasCurve;
1144
1145        SetStatus(DllExports::GdipPathIterHasCurve(nativeIterator, &hasCurve));
1146
1147        return hasCurve;
1148    }
1149
1150    VOID Rewind()
1151    {
1152        SetStatus(DllExports::GdipPathIterRewind(nativeIterator));
1153    }
1154
1155    INT Enumerate(OUT PointF *points,
1156                  OUT BYTE *types,
1157                  IN INT count)
1158    {
1159        INT resultCount;
1160
1161        SetStatus(DllExports::GdipPathIterEnumerate(nativeIterator,
1162            &resultCount, points, types, count));
1163
1164        return resultCount;
1165    }
1166
1167    INT CopyData(OUT PointF* points,
1168                 OUT BYTE* types,
1169                 IN INT startIndex,
1170                 IN INT endIndex)
1171    {
1172        INT resultCount;
1173
1174        SetStatus(DllExports::GdipPathIterCopyData(nativeIterator,
1175            &resultCount, points, types, startIndex, endIndex));
1176
1177        return resultCount;
1178    }
1179
1180    Status GetLastStatus() const
1181    {
1182        Status lastStatus = lastResult;
1183        lastResult = Ok;
1184
1185        return lastStatus;
1186    }
1187
1188#ifdef DCR_USE_NEW_250932
1189
1190private:
1191    GraphicsPathIterator(const GraphicsPathIterator &);
1192    GraphicsPathIterator& operator=(const GraphicsPathIterator &);
1193
1194#endif
1195
1196protected:
1197    VOID SetNativeIterator(GpPathIterator *nativeIterator)
1198    {
1199        this->nativeIterator = nativeIterator;
1200    }
1201
1202    Status SetStatus(Status status) const
1203    {
1204        if (status != Ok)
1205            return (lastResult = status);
1206        else
1207            return status;
1208    }
1209
1210protected:
1211    GpPathIterator* nativeIterator;
1212    mutable Status lastResult;
1213};
1214
1215
1216//--------------------------------------------------------------------------
1217// Represent polygon gradient brush object
1218//--------------------------------------------------------------------------
1219
1220class PathGradientBrush : public Brush
1221{
1222public:
1223    friend class Pen;
1224
1225    PathGradientBrush(
1226        IN const PointF* points,
1227        IN INT count,
1228        IN WrapMode wrapMode = WrapModeClamp)
1229    {
1230        GpPathGradient *brush = NULL;
1231
1232        lastResult = DllExports::GdipCreatePathGradient(
1233                                        points, count,
1234                                        wrapMode, &brush);
1235        SetNativeBrush(brush);
1236    }
1237
1238    PathGradientBrush(
1239        IN const Point* points,
1240        IN INT count,
1241        IN WrapMode wrapMode = WrapModeClamp)
1242    {
1243        GpPathGradient *brush = NULL;
1244
1245        lastResult = DllExports::GdipCreatePathGradientI(
1246                                        points, count,
1247                                        wrapMode, &brush);
1248
1249        SetNativeBrush(brush);
1250    }
1251
1252    PathGradientBrush(
1253        IN const GraphicsPath* path
1254        )
1255    {
1256        GpPathGradient *brush = NULL;
1257
1258        lastResult = DllExports::GdipCreatePathGradientFromPath(
1259                                        path->nativePath, &brush);
1260        SetNativeBrush(brush);
1261    }
1262
1263    // Get/set colors
1264
1265    Status GetCenterColor(OUT Color* color) const
1266    {
1267        ARGB argb;
1268
1269        if (color == NULL)
1270        {
1271            return SetStatus(InvalidParameter);
1272        }
1273
1274        SetStatus(DllExports::GdipGetPathGradientCenterColor(
1275                       (GpPathGradient*) nativeBrush, &argb));
1276
1277        color->SetValue(argb);
1278
1279        return lastResult;
1280    }
1281
1282    Status SetCenterColor(IN const Color& color)
1283    {
1284        SetStatus(DllExports::GdipSetPathGradientCenterColor(
1285                       (GpPathGradient*) nativeBrush,
1286                       color.GetValue()));
1287
1288        return lastResult;
1289    }
1290
1291    INT GetPointCount() const
1292    {
1293        INT count;
1294
1295        SetStatus(DllExports::GdipGetPathGradientPointCount(
1296                       (GpPathGradient*) nativeBrush, &count));
1297
1298        return count;
1299    }
1300
1301    INT GetSurroundColorCount() const
1302    {
1303        INT count;
1304
1305        SetStatus(DllExports::GdipGetPathGradientSurroundColorCount(
1306                       (GpPathGradient*) nativeBrush, &count));
1307
1308        return count;
1309    }
1310
1311    Status GetSurroundColors(OUT Color* colors,
1312                             IN OUT INT* count) const
1313    {
1314        if(colors == NULL || count == NULL)
1315        {
1316            return SetStatus(InvalidParameter);
1317        }
1318
1319        INT count1;
1320
1321        SetStatus(DllExports::GdipGetPathGradientSurroundColorCount(
1322                        (GpPathGradient*) nativeBrush, &count1));
1323
1324        if(lastResult != Ok)
1325            return lastResult;
1326
1327        if((*count < count1) || (count1 <= 0))
1328            return SetStatus(InsufficientBuffer);
1329
1330        ARGB* argbs = (ARGB*) new ARGB[count1];
1331        if(argbs == NULL)
1332            return SetStatus(OutOfMemory);
1333
1334        SetStatus(DllExports::GdipGetPathGradientSurroundColorsWithCount(
1335                    (GpPathGradient*)nativeBrush, argbs, &count1));
1336
1337        if(lastResult == Ok)
1338        {
1339            for(INT i = 0; i < count1; i++)
1340            {
1341                colors[i].SetValue(argbs[i]);
1342            }
1343            *count = count1;
1344        }
1345
1346        delete [] argbs;
1347        return lastResult;
1348    }
1349
1350    Status SetSurroundColors(IN const Color* colors,
1351                             IN OUT INT* count)
1352    {
1353        if(colors == NULL || count == NULL)
1354        {
1355            return SetStatus(InvalidParameter);
1356        }
1357
1358        INT count1 = GetPointCount();
1359
1360        if((*count > count1) || (count1 <= 0))
1361            return SetStatus(InvalidParameter);
1362
1363        count1 = *count;
1364
1365        ARGB* argbs = (ARGB*) new ARGB[count1];
1366        if(argbs == NULL)
1367            return SetStatus(OutOfMemory);
1368
1369        for(INT i = 0; i < count1; i++)
1370        {
1371            argbs[i] = colors[i].GetValue();
1372        }
1373
1374        SetStatus(DllExports::GdipSetPathGradientSurroundColorsWithCount(
1375                    (GpPathGradient*)nativeBrush, argbs, &count1));
1376
1377        if(lastResult == Ok)
1378            *count = count1;
1379
1380        delete [] argbs;
1381
1382        return lastResult;
1383    }
1384
1385    Status GetGraphicsPath(OUT GraphicsPath* path) const
1386    {
1387        if(path == NULL)
1388            return SetStatus(InvalidParameter);
1389
1390        return SetStatus(DllExports::GdipGetPathGradientPath(
1391                    (GpPathGradient*)nativeBrush, path->nativePath));
1392    }
1393
1394    Status SetGraphicsPath(IN const GraphicsPath* path)
1395    {
1396        if(path == NULL)
1397            return SetStatus(InvalidParameter);
1398
1399        return SetStatus(DllExports::GdipSetPathGradientPath(
1400                    (GpPathGradient*)nativeBrush, path->nativePath));
1401    }
1402
1403    Status GetCenterPoint(OUT PointF* point) const
1404    {
1405        return SetStatus(DllExports::GdipGetPathGradientCenterPoint(
1406                                (GpPathGradient*)nativeBrush,
1407                                point));
1408    }
1409
1410
1411    Status GetCenterPoint(OUT Point* point) const
1412    {
1413        return SetStatus(DllExports::GdipGetPathGradientCenterPointI(
1414                                (GpPathGradient*)nativeBrush,
1415                                point));
1416    }
1417
1418    Status SetCenterPoint(IN const PointF& point)
1419    {
1420        return SetStatus(DllExports::GdipSetPathGradientCenterPoint(
1421                                (GpPathGradient*)nativeBrush,
1422                                &point));
1423    }
1424
1425    Status SetCenterPoint(IN const Point& point)
1426    {
1427        return SetStatus(DllExports::GdipSetPathGradientCenterPointI(
1428                                (GpPathGradient*)nativeBrush,
1429                                &point));
1430    }
1431
1432    Status GetRectangle(OUT RectF* rect) const
1433    {
1434        return SetStatus(DllExports::GdipGetPathGradientRect(
1435                            (GpPathGradient*)nativeBrush, rect));
1436    }
1437
1438    Status GetRectangle(OUT Rect* rect) const
1439    {
1440        return SetStatus(DllExports::GdipGetPathGradientRectI(
1441                            (GpPathGradient*)nativeBrush, rect));
1442    }
1443
1444    // Gamma correction.
1445
1446    Status SetGammaCorrection(IN BOOL useGammaCorrection)
1447    {
1448        return SetStatus(DllExports::GdipSetPathGradientGammaCorrection(
1449            (GpPathGradient*)nativeBrush, useGammaCorrection));
1450    }
1451
1452    BOOL GetGammaCorrection() const
1453    {
1454        BOOL useGammaCorrection;
1455
1456        SetStatus(DllExports::GdipGetPathGradientGammaCorrection(
1457            (GpPathGradient*)nativeBrush, &useGammaCorrection));
1458
1459        return useGammaCorrection;
1460    }
1461
1462    INT GetBlendCount() const
1463    {
1464       INT count = 0;
1465
1466       SetStatus(DllExports::GdipGetPathGradientBlendCount(
1467                           (GpPathGradient*) nativeBrush, &count));
1468
1469       return count;
1470    }
1471
1472    Status GetBlend(OUT REAL* blendFactors,
1473                    OUT REAL* blendPositions,
1474                    IN INT count) const
1475    {
1476        return SetStatus(DllExports::GdipGetPathGradientBlend(
1477                            (GpPathGradient*)nativeBrush,
1478                            blendFactors, blendPositions, count));
1479    }
1480
1481    Status SetBlend(IN const REAL* blendFactors,
1482                    IN const REAL* blendPositions,
1483                    IN INT count)
1484    {
1485        return SetStatus(DllExports::GdipSetPathGradientBlend(
1486                            (GpPathGradient*)nativeBrush,
1487                            blendFactors, blendPositions, count));
1488    }
1489
1490    INT GetInterpolationColorCount() const
1491    {
1492       INT count = 0;
1493
1494       SetStatus(DllExports::GdipGetPathGradientPresetBlendCount(
1495                        (GpPathGradient*) nativeBrush, &count));
1496
1497       return count;
1498    }
1499
1500    Status SetInterpolationColors(IN const Color* presetColors,
1501                                  IN const REAL* blendPositions,
1502                                  IN INT count)
1503    {
1504        if ((count <= 0) || !presetColors)
1505        {
1506            return SetStatus(InvalidParameter);
1507        }
1508
1509        ARGB* argbs = (ARGB*) new ARGB[count];
1510        if(argbs)
1511        {
1512            for(INT i = 0; i < count; i++)
1513            {
1514                argbs[i] = presetColors[i].GetValue();
1515            }
1516
1517            Status status = SetStatus(DllExports::GdipSetPathGradientPresetBlend(
1518                                    (GpPathGradient*) nativeBrush,
1519                                    argbs,
1520                                    blendPositions,
1521                                    count));
1522            delete[] argbs;
1523            return status;
1524        }
1525        else
1526        {
1527            return SetStatus(OutOfMemory);
1528        }
1529    }
1530
1531    Status GetInterpolationColors(OUT Color* presetColors,
1532                                  OUT REAL* blendPositions,
1533                                  IN INT count) const
1534    {
1535        if ((count <= 0) || !presetColors)
1536        {
1537            return SetStatus(InvalidParameter);
1538        }
1539
1540        ARGB* argbs = (ARGB*) new ARGB[count];
1541
1542        if (!argbs)
1543        {
1544            return SetStatus(OutOfMemory);
1545        }
1546
1547        GpStatus status = SetStatus(DllExports::GdipGetPathGradientPresetBlend(
1548                                (GpPathGradient*)nativeBrush,
1549                                argbs,
1550                                blendPositions,
1551                                count));
1552
1553        for(INT i = 0; i < count; i++)
1554        {
1555            presetColors[i] = Color(argbs[i]);
1556        }
1557        delete [] argbs;
1558
1559        return status;
1560    }
1561
1562    Status SetBlendBellShape(IN REAL focus,
1563                             IN REAL scale = 1.0)
1564    {
1565        return SetStatus(DllExports::GdipSetPathGradientSigmaBlend(
1566                            (GpPathGradient*)nativeBrush, focus, scale));
1567    }
1568
1569    #ifdef DCR_USE_NEW_145135
1570    Status SetBlendTriangularShape(
1571        IN REAL focus,
1572        IN REAL scale = 1.0
1573    )
1574    #else
1575    Status SetBlendTrianglarShape(IN REAL focus,
1576                                  IN REAL scale = 1.0)
1577    #endif
1578    {
1579        return SetStatus(DllExports::GdipSetPathGradientLinearBlend(
1580                            (GpPathGradient*)nativeBrush, focus, scale));
1581    }
1582
1583    /**
1584     * Get/set brush transform
1585     */
1586    Status GetTransform(OUT Matrix *matrix) const
1587    {
1588        return SetStatus(DllExports::GdipGetPathGradientTransform(
1589                            (GpPathGradient*) nativeBrush, matrix->nativeMatrix));
1590    }
1591
1592    Status SetTransform(IN const Matrix* matrix)
1593    {
1594        return SetStatus(DllExports::GdipSetPathGradientTransform(
1595                            (GpPathGradient*) nativeBrush, matrix->nativeMatrix));
1596    }
1597
1598    Status ResetTransform()
1599    {
1600        return SetStatus(DllExports::GdipResetPathGradientTransform((GpPathGradient*)nativeBrush));
1601    }
1602
1603    Status MultiplyTransform(IN const Matrix* matrix,
1604                             IN MatrixOrder order = MatrixOrderPrepend)
1605    {
1606        return SetStatus(DllExports::GdipMultiplyPathGradientTransform((GpPathGradient*)nativeBrush,
1607                                                                matrix->nativeMatrix,
1608                                                                order));
1609    }
1610
1611    Status TranslateTransform(IN REAL dx,
1612                              IN REAL dy,
1613                              IN MatrixOrder order = MatrixOrderPrepend)
1614    {
1615        return SetStatus(DllExports::GdipTranslatePathGradientTransform((GpPathGradient*)nativeBrush,
1616                                                               dx, dy, order));
1617    }
1618
1619    Status ScaleTransform(IN REAL sx,
1620                          IN REAL sy,
1621                          IN MatrixOrder order = MatrixOrderPrepend)
1622    {
1623        return SetStatus(DllExports::GdipScalePathGradientTransform((GpPathGradient*)nativeBrush,
1624                                                             sx, sy, order));
1625    }
1626
1627    Status RotateTransform(IN REAL angle,
1628                           IN MatrixOrder order = MatrixOrderPrepend)
1629    {
1630        return SetStatus(DllExports::GdipRotatePathGradientTransform((GpPathGradient*)nativeBrush,
1631                                                              angle, order));
1632    }
1633
1634    /**
1635     * Get/set brush focus scales
1636     */
1637    Status GetFocusScales(OUT REAL* xScale,
1638                          OUT REAL* yScale) const
1639    {
1640        return SetStatus(DllExports::GdipGetPathGradientFocusScales(
1641                            (GpPathGradient*) nativeBrush, xScale, yScale));
1642    }
1643
1644    Status SetFocusScales(IN REAL xScale,
1645                          IN REAL yScale)
1646    {
1647        return SetStatus(DllExports::GdipSetPathGradientFocusScales(
1648                            (GpPathGradient*) nativeBrush, xScale, yScale));
1649    }
1650
1651    /**
1652     * Get/set brush wrapping mode
1653     */
1654    WrapMode GetWrapMode() const
1655    {
1656        WrapMode wrapMode;
1657
1658        SetStatus(DllExports::GdipGetPathGradientWrapMode(
1659                     (GpPathGradient*) nativeBrush, &wrapMode));
1660
1661        return wrapMode;
1662    }
1663
1664    Status SetWrapMode(IN WrapMode wrapMode)
1665    {
1666        return SetStatus(DllExports::GdipSetPathGradientWrapMode(
1667                            (GpPathGradient*) nativeBrush, wrapMode));
1668    }
1669
1670#ifdef DCR_USE_NEW_250932
1671
1672private:
1673    PathGradientBrush(const PathGradientBrush &);
1674    PathGradientBrush& operator=(const PathGradientBrush &);
1675
1676#endif
1677
1678protected:
1679
1680    PathGradientBrush()
1681    {
1682    }
1683};
1684
1685
1686#endif // !_GRAPHICSPATH_HPP
1687