New test.
[mono.git] / mcs / class / System.Drawing / System.Drawing.Drawing2D / PathGradientBrush.cs
1 //
2 // System.Drawing.Drawing2D.PathGradientBrush.cs
3 //
4 // Authors:
5 //   Dennis Hayes (dennish@Raytek.com)
6 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 //   Ravindra (rkumar@novell.com)
8 //
9 // Copyright (C) 2002/3 Ximian, Inc. http://www.ximian.com
10 // Copyright (C) 2004,2006 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.ComponentModel;
33
34 namespace System.Drawing.Drawing2D {
35
36         [MonoTODO ("libgdiplus/cairo doesn't support path gradients - unless it can be mapped to a radial gradient")]
37         public sealed class PathGradientBrush : Brush {
38
39                 internal PathGradientBrush (IntPtr native) : base (native)
40                 {
41                 }
42
43                 public PathGradientBrush (GraphicsPath path)
44                 {
45                         if (path == null)
46                                 throw new ArgumentNullException ("path");
47
48                         Status status = GDIPlus.GdipCreatePathGradientFromPath (path.NativeObject, out nativeObject);
49                         GDIPlus.CheckStatus (status);
50                 }
51
52                 public PathGradientBrush (Point [] points) : this (points, WrapMode.Clamp)
53                 {
54                 }
55
56                 public PathGradientBrush (PointF [] points) : this (points, WrapMode.Clamp)
57                 {
58                 }
59
60                 public PathGradientBrush (Point [] points, WrapMode wrapMode)
61                 {
62                         if (points == null)
63                                 throw new ArgumentNullException ("points");
64                         if ((wrapMode < WrapMode.Tile) || (wrapMode > WrapMode.Clamp))
65                                 throw new InvalidEnumArgumentException ("WrapMode");
66
67                         Status status = GDIPlus.GdipCreatePathGradientI (points, points.Length, wrapMode, out nativeObject);
68                         GDIPlus.CheckStatus (status);
69                 }
70
71                 public PathGradientBrush (PointF [] points, WrapMode wrapMode)
72                 {
73                         if (points == null)
74                                 throw new ArgumentNullException ("points");
75                         if ((wrapMode < WrapMode.Tile) || (wrapMode > WrapMode.Clamp))
76                                 throw new InvalidEnumArgumentException ("WrapMode");
77
78                         Status status = GDIPlus.GdipCreatePathGradient (points, points.Length, wrapMode, out nativeObject);
79                         GDIPlus.CheckStatus (status);
80                 }
81
82                 // Properties
83
84                 public Blend Blend {
85                         get {
86                                 int count;
87                                 Status status = GDIPlus.GdipGetPathGradientBlendCount (nativeObject, out count);
88                                 GDIPlus.CheckStatus (status);
89                                 float [] factors = new float [count];
90                                 float [] positions = new float [count];
91                                 status = GDIPlus.GdipGetPathGradientBlend (nativeObject, factors, positions, count);
92                                 GDIPlus.CheckStatus (status);
93
94                                 Blend blend = new Blend ();
95                                 blend.Factors = factors;
96                                 blend.Positions = positions;
97
98                                 return blend;
99                         }
100                         set {
101                                 int count;
102                                 float [] factors = value.Factors;
103                                 float [] positions = value.Positions;
104                                 count = factors.Length;
105
106                                 if (count == 0 || positions.Length == 0)
107                                         throw new ArgumentException ("Invalid Blend object. It should have at least 2 elements in each of the factors and positions arrays.");
108
109                                 if (count != positions.Length)
110                                         throw new ArgumentException ("Invalid Blend object. It should contain the same number of factors and positions values.");
111
112                                 if (positions [0] != 0.0F)
113                                         throw new ArgumentException ("Invalid Blend object. The positions array must have 0.0 as its first element.");
114
115                                 if (positions [count - 1] != 1.0F)
116                                         throw new ArgumentException ("Invalid Blend object. The positions array must have 1.0 as its last element.");
117
118                                 Status status = GDIPlus.GdipSetPathGradientBlend (nativeObject, factors, positions, count);
119                                 GDIPlus.CheckStatus (status);
120                         }
121                 }
122
123                 public Color CenterColor {
124                         get {
125                                 int centerColor;
126                                 Status status = GDIPlus.GdipGetPathGradientCenterColor (nativeObject, out centerColor);
127                                 GDIPlus.CheckStatus (status);
128                                 return Color.FromArgb (centerColor);
129                         }
130                         set {
131                                 Status status = GDIPlus.GdipSetPathGradientCenterColor (nativeObject, value.ToArgb ());
132                                 GDIPlus.CheckStatus (status);
133                         }
134                 }
135
136                 public PointF CenterPoint {
137                         get {
138                                 PointF center;
139                                 Status status = GDIPlus.GdipGetPathGradientCenterPoint (nativeObject, out center);
140                                 GDIPlus.CheckStatus (status);
141
142                                 return center;
143                         }
144                         set {
145                                 PointF center = value;
146                                 Status status = GDIPlus.GdipSetPathGradientCenterPoint (nativeObject, ref center);
147                                 GDIPlus.CheckStatus (status);
148                         }
149                 }
150
151                 public PointF FocusScales {
152                         get {
153                                 float xScale;
154                                 float yScale;
155                                 Status status = GDIPlus.GdipGetPathGradientFocusScales (nativeObject, out xScale, out yScale);
156                                 GDIPlus.CheckStatus (status);
157
158                                 return new PointF (xScale, yScale);
159                         }
160                         set {
161                                 Status status = GDIPlus.GdipSetPathGradientFocusScales (nativeObject, value.X, value.Y);
162                                 GDIPlus.CheckStatus (status);
163                         }
164                 }
165
166                 public ColorBlend InterpolationColors {
167                         get {
168                                 int count;
169                                 Status status = GDIPlus.GdipGetPathGradientPresetBlendCount (nativeObject, out count);
170                                 GDIPlus.CheckStatus (status);
171                                 // if no failure, then the "managed" minimum is 1
172                                 if (count < 1)
173                                         count = 1;
174
175                                 int [] intcolors = new int [count];
176                                 float [] positions = new float [count];
177                                 // status would fail if we ask points or types with a < 2 count
178                                 if (count > 1) {
179                                         status = GDIPlus.GdipGetPathGradientPresetBlend (nativeObject, intcolors, positions, count);
180                                         GDIPlus.CheckStatus (status);
181                                 }
182
183                                 ColorBlend interpolationColors = new ColorBlend ();
184                                 Color [] colors = new Color [count];
185                                 for (int i = 0; i < count; i++)
186                                         colors [i] = Color.FromArgb (intcolors [i]);
187                                 interpolationColors.Colors = colors;
188                                 interpolationColors.Positions = positions;
189
190                                 return interpolationColors;
191                         }
192                         set {
193                                 int count;
194                                 Color [] colors = value.Colors;
195                                 float [] positions = value.Positions;
196                                 count = colors.Length;
197
198                                 if (count == 0 || positions.Length == 0)
199                                         throw new ArgumentException ("Invalid ColorBlend object. It should have at least 2 elements in each of the colors and positions arrays.");
200
201                                 if (count != positions.Length)
202                                         throw new ArgumentException ("Invalid ColorBlend object. It should contain the same number of positions and color values.");
203
204                                 if (positions [0] != 0.0F)
205                                         throw new ArgumentException ("Invalid ColorBlend object. The positions array must have 0.0 as its first element.");
206
207                                 if (positions [count - 1] != 1.0F)
208                                         throw new ArgumentException ("Invalid ColorBlend object. The positions array must have 1.0 as its last element.");
209
210                                 int [] blend = new int [colors.Length];
211                                 for (int i = 0; i < colors.Length; i++)
212                                         blend [i] = colors [i].ToArgb ();
213
214                                 Status status = GDIPlus.GdipSetPathGradientPresetBlend (nativeObject, blend, positions, count);
215                                 GDIPlus.CheckStatus (status);
216                         }
217                 }
218
219                 public RectangleF Rectangle {
220                         get {
221                                 RectangleF rect;
222                                 Status status = GDIPlus.GdipGetPathGradientRect (nativeObject, out rect);
223                                 GDIPlus.CheckStatus (status);
224
225                                 return rect;
226                         }
227                 }
228
229                 public Color [] SurroundColors {
230                         get {
231                                 int count;
232                                 Status status = GDIPlus.GdipGetPathGradientSurroundColorCount (nativeObject, out count);
233                                 GDIPlus.CheckStatus (status);
234
235                                 int [] intcolors = new int [count];
236                                 status = GDIPlus.GdipGetPathGradientSurroundColorsWithCount (nativeObject, intcolors, ref count);
237                                 GDIPlus.CheckStatus (status);
238
239                                 Color [] colors = new Color [count];
240                                 for (int i = 0; i < count; i++)
241                                         colors [i] = Color.FromArgb (intcolors [i]);
242
243                                 return colors;
244                         }
245                         set {
246                                 int count = value.Length;
247                                 int [] colors = new int [count];
248                                 for (int i = 0; i < count; i++)
249                                         colors [i] = value [i].ToArgb ();
250
251                                 Status status = GDIPlus.GdipSetPathGradientSurroundColorsWithCount (nativeObject, colors, ref count);
252                                 GDIPlus.CheckStatus (status);
253                         }
254                 }
255
256                 public Matrix Transform {
257                         get {
258                                 Matrix matrix = new Matrix ();
259                                 Status status = GDIPlus.GdipGetPathGradientTransform (nativeObject, matrix.nativeMatrix);
260                                 GDIPlus.CheckStatus (status);
261
262                                 return matrix;
263                         }
264                         set {
265                                 if (value == null)
266                                         throw new ArgumentNullException ("Transform");
267
268                                 Status status = GDIPlus.GdipSetPathGradientTransform (nativeObject, value.nativeMatrix);
269                                 GDIPlus.CheckStatus (status);
270                         }
271                 }
272
273                 public WrapMode WrapMode {
274                         get {
275                                 WrapMode wrapMode;
276                                 Status status = GDIPlus.GdipGetPathGradientWrapMode (nativeObject, out wrapMode);
277                                 GDIPlus.CheckStatus (status);
278
279                                 return wrapMode;
280                         }
281                         set {
282                                 if ((value < WrapMode.Tile) || (value > WrapMode.Clamp))
283                                         throw new InvalidEnumArgumentException ("WrapMode");
284
285                                 Status status = GDIPlus.GdipSetPathGradientWrapMode (nativeObject, value);
286                                 GDIPlus.CheckStatus (status);
287                         }
288                 }
289
290                 // Methods
291
292                 public void MultiplyTransform (Matrix matrix)
293                 {
294                         MultiplyTransform (matrix, MatrixOrder.Prepend);
295                 }
296
297                 public void MultiplyTransform (Matrix matrix, MatrixOrder order)
298                 {
299                         if (matrix == null)
300                                 throw new ArgumentNullException ("matrix");
301
302                         Status status = GDIPlus.GdipMultiplyPathGradientTransform (nativeObject, matrix.nativeMatrix, order);
303                         GDIPlus.CheckStatus (status);
304                 }
305
306                 public void ResetTransform ()
307                 {
308                         Status status = GDIPlus.GdipResetPathGradientTransform (nativeObject);
309                         GDIPlus.CheckStatus (status);
310                 }
311
312                 public void RotateTransform (float angle)
313                 {
314                         RotateTransform (angle, MatrixOrder.Prepend);
315                 }
316
317                 public void RotateTransform (float angle, MatrixOrder order)
318                 {
319                         Status status = GDIPlus.GdipRotatePathGradientTransform (nativeObject, angle, order);
320                         GDIPlus.CheckStatus (status);
321                 }
322
323                 public void ScaleTransform (float sx, float sy)
324                 {
325                         ScaleTransform (sx, sy, MatrixOrder.Prepend);
326                 }
327
328                 public void ScaleTransform (float sx, float sy, MatrixOrder order)
329                 {
330                         Status status = GDIPlus.GdipScalePathGradientTransform (nativeObject, sx, sy, order);
331                         GDIPlus.CheckStatus (status);
332                 }
333
334                 public void SetBlendTriangularShape (float focus)
335                 {
336                         SetBlendTriangularShape (focus, 1.0F);
337                 }
338
339                 public void SetBlendTriangularShape (float focus, float scale)
340                 {
341                         if (focus < 0 || focus > 1 || scale < 0 || scale > 1)
342                                 throw new ArgumentException ("Invalid parameter passed.");
343
344                         Status status = GDIPlus.GdipSetPathGradientLinearBlend (nativeObject, focus, scale);
345                         GDIPlus.CheckStatus (status);
346                 }
347
348                 public void SetSigmaBellShape (float focus)
349                 {
350                         SetSigmaBellShape (focus, 1.0F);
351                 }
352
353                 public void SetSigmaBellShape (float focus, float scale)
354                 {
355                         if (focus < 0 || focus > 1 || scale < 0 || scale > 1)
356                                 throw new ArgumentException ("Invalid parameter passed.");
357
358                         Status status = GDIPlus.GdipSetPathGradientSigmaBlend (nativeObject, focus, scale);
359                         GDIPlus.CheckStatus (status);
360                 }
361
362                 public void TranslateTransform (float dx, float dy)
363                 {
364                         TranslateTransform (dx, dy, MatrixOrder.Prepend);
365                 }
366
367                 public void TranslateTransform (float dx, float dy, MatrixOrder order)
368                 {
369                         Status status = GDIPlus.GdipTranslatePathGradientTransform (nativeObject, dx, dy, order);
370                         GDIPlus.CheckStatus (status);
371                 }
372
373                 public override object Clone ()
374                 {
375                         IntPtr clonePtr;
376                         Status status = GDIPlus.GdipCloneBrush (nativeObject, out clonePtr);
377                         GDIPlus.CheckStatus (status);
378
379                         PathGradientBrush clone = new PathGradientBrush (clonePtr);
380                         return clone;
381                 }
382         }
383 }