Bump corefx
[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 using System.Runtime.InteropServices;
34
35 namespace System.Drawing.Drawing2D {
36
37         [MonoTODO ("libgdiplus/cairo doesn't support path gradients - unless it can be mapped to a radial gradient")]
38         public sealed class PathGradientBrush : Brush {
39
40                 internal PathGradientBrush (IntPtr native)
41                 {
42                         SetNativeBrush (native);
43                 }
44
45                 public PathGradientBrush (GraphicsPath path)
46                 {
47                         if (path == null)
48                                 throw new ArgumentNullException ("path");
49
50                         IntPtr nativeObject;
51                         Status status = GDIPlus.GdipCreatePathGradientFromPath (path.nativePath, out nativeObject);
52                         GDIPlus.CheckStatus (status);
53                         SetNativeBrush (nativeObject);
54                 }
55
56                 public PathGradientBrush (Point [] points) : this (points, WrapMode.Clamp)
57                 {
58                 }
59
60                 public PathGradientBrush (PointF [] points) : this (points, WrapMode.Clamp)
61                 {
62                 }
63
64                 public PathGradientBrush (Point [] points, WrapMode wrapMode)
65                 {
66                         if (points == null)
67                                 throw new ArgumentNullException ("points");
68                         if ((wrapMode < WrapMode.Tile) || (wrapMode > WrapMode.Clamp))
69                                 throw new InvalidEnumArgumentException ("WrapMode");
70
71                         IntPtr nativeObject;
72                         Status status = GDIPlus.GdipCreatePathGradientI (points, points.Length, wrapMode, out nativeObject);
73                         GDIPlus.CheckStatus (status);
74                         SetNativeBrush (nativeObject);
75                 }
76
77                 public PathGradientBrush (PointF [] points, WrapMode wrapMode)
78                 {
79                         if (points == null)
80                                 throw new ArgumentNullException ("points");
81                         if ((wrapMode < WrapMode.Tile) || (wrapMode > WrapMode.Clamp))
82                                 throw new InvalidEnumArgumentException ("WrapMode");
83
84                         IntPtr nativeObject;
85                         Status status = GDIPlus.GdipCreatePathGradient (points, points.Length, wrapMode, out nativeObject);
86                         GDIPlus.CheckStatus (status);
87                         SetNativeBrush (nativeObject);
88                 }
89
90                 // Properties
91
92                 public Blend Blend {
93                         get {
94                                 int count;
95                                 Status status = GDIPlus.GdipGetPathGradientBlendCount (NativeBrush, out count);
96                                 GDIPlus.CheckStatus (status);
97                                 float [] factors = new float [count];
98                                 float [] positions = new float [count];
99                                 status = GDIPlus.GdipGetPathGradientBlend (NativeBrush, factors, positions, count);
100                                 GDIPlus.CheckStatus (status);
101
102                                 Blend blend = new Blend ();
103                                 blend.Factors = factors;
104                                 blend.Positions = positions;
105
106                                 return blend;
107                         }
108                         set {
109                                 // no null check, MS throws a NullReferenceException here
110                                 int count;
111                                 float [] factors = value.Factors;
112                                 float [] positions = value.Positions;
113                                 count = factors.Length;
114
115                                 if (count == 0 || positions.Length == 0)
116                                         throw new ArgumentException ("Invalid Blend object. It should have at least 2 elements in each of the factors and positions arrays.");
117
118                                 if (count != positions.Length)
119                                         throw new ArgumentException ("Invalid Blend object. It should contain the same number of factors and positions values.");
120
121                                 if (positions [0] != 0.0F)
122                                         throw new ArgumentException ("Invalid Blend object. The positions array must have 0.0 as its first element.");
123
124                                 if (positions [count - 1] != 1.0F)
125                                         throw new ArgumentException ("Invalid Blend object. The positions array must have 1.0 as its last element.");
126
127                                 Status status = GDIPlus.GdipSetPathGradientBlend (NativeBrush, factors, positions, count);
128                                 GDIPlus.CheckStatus (status);
129                         }
130                 }
131
132                 public Color CenterColor {
133                         get {
134                                 int centerColor;
135                                 Status status = GDIPlus.GdipGetPathGradientCenterColor (NativeBrush, out centerColor);
136                                 GDIPlus.CheckStatus (status);
137                                 return Color.FromArgb (centerColor);
138                         }
139                         set {
140                                 Status status = GDIPlus.GdipSetPathGradientCenterColor (NativeBrush, value.ToArgb ());
141                                 GDIPlus.CheckStatus (status);
142                         }
143                 }
144
145                 public PointF CenterPoint {
146                         get {
147                                 PointF center;
148                                 Status status = GDIPlus.GdipGetPathGradientCenterPoint (NativeBrush, out center);
149                                 GDIPlus.CheckStatus (status);
150
151                                 return center;
152                         }
153                         set {
154                                 PointF center = value;
155                                 Status status = GDIPlus.GdipSetPathGradientCenterPoint (NativeBrush, ref center);
156                                 GDIPlus.CheckStatus (status);
157                         }
158                 }
159
160                 public PointF FocusScales {
161                         get {
162                                 float xScale;
163                                 float yScale;
164                                 Status status = GDIPlus.GdipGetPathGradientFocusScales (NativeBrush, out xScale, out yScale);
165                                 GDIPlus.CheckStatus (status);
166
167                                 return new PointF (xScale, yScale);
168                         }
169                         set {
170                                 Status status = GDIPlus.GdipSetPathGradientFocusScales (NativeBrush, value.X, value.Y);
171                                 GDIPlus.CheckStatus (status);
172                         }
173                 }
174
175                 public ColorBlend InterpolationColors {
176                         get {
177                                 int count;
178                                 Status status = GDIPlus.GdipGetPathGradientPresetBlendCount (NativeBrush, out count);
179                                 GDIPlus.CheckStatus (status);
180                                 // if no failure, then the "managed" minimum is 1
181                                 if (count < 1)
182                                         count = 1;
183
184                                 int [] intcolors = new int [count];
185                                 float [] positions = new float [count];
186                                 // status would fail if we ask points or types with a < 2 count
187                                 if (count > 1) {
188                                         status = GDIPlus.GdipGetPathGradientPresetBlend (NativeBrush, intcolors, positions, count);
189                                         GDIPlus.CheckStatus (status);
190                                 }
191
192                                 ColorBlend interpolationColors = new ColorBlend ();
193                                 Color [] colors = new Color [count];
194                                 for (int i = 0; i < count; i++)
195                                         colors [i] = Color.FromArgb (intcolors [i]);
196                                 interpolationColors.Colors = colors;
197                                 interpolationColors.Positions = positions;
198
199                                 return interpolationColors;
200                         }
201                         set {
202                                 // no null check, MS throws a NullReferenceException here
203                                 int count;
204                                 Color [] colors = value.Colors;
205                                 float [] positions = value.Positions;
206                                 count = colors.Length;
207
208                                 if (count == 0 || positions.Length == 0)
209                                         throw new ArgumentException ("Invalid ColorBlend object. It should have at least 2 elements in each of the colors and positions arrays.");
210
211                                 if (count != positions.Length)
212                                         throw new ArgumentException ("Invalid ColorBlend object. It should contain the same number of positions and color values.");
213
214                                 if (positions [0] != 0.0F)
215                                         throw new ArgumentException ("Invalid ColorBlend object. The positions array must have 0.0 as its first element.");
216
217                                 if (positions [count - 1] != 1.0F)
218                                         throw new ArgumentException ("Invalid ColorBlend object. The positions array must have 1.0 as its last element.");
219
220                                 int [] blend = new int [colors.Length];
221                                 for (int i = 0; i < colors.Length; i++)
222                                         blend [i] = colors [i].ToArgb ();
223
224                                 Status status = GDIPlus.GdipSetPathGradientPresetBlend (NativeBrush, blend, positions, count);
225                                 GDIPlus.CheckStatus (status);
226                         }
227                 }
228
229                 public RectangleF Rectangle {
230                         get {
231                                 RectangleF rect;
232                                 Status status = GDIPlus.GdipGetPathGradientRect (NativeBrush, out rect);
233                                 GDIPlus.CheckStatus (status);
234
235                                 return rect;
236                         }
237                 }
238
239                 public Color [] SurroundColors {
240                         get {
241                                 int count;
242                                 Status status = GDIPlus.GdipGetPathGradientSurroundColorCount (NativeBrush, out count);
243                                 GDIPlus.CheckStatus (status);
244
245                                 int [] intcolors = new int [count];
246                                 status = GDIPlus.GdipGetPathGradientSurroundColorsWithCount (NativeBrush, intcolors, ref count);
247                                 GDIPlus.CheckStatus (status);
248
249                                 Color [] colors = new Color [count];
250                                 for (int i = 0; i < count; i++)
251                                         colors [i] = Color.FromArgb (intcolors [i]);
252
253                                 return colors;
254                         }
255                         set {
256                                 // no null check, MS throws a NullReferenceException here
257                                 int count = value.Length;
258                                 int [] colors = new int [count];
259                                 for (int i = 0; i < count; i++)
260                                         colors [i] = value [i].ToArgb ();
261
262                                 Status status = GDIPlus.GdipSetPathGradientSurroundColorsWithCount (NativeBrush, colors, ref count);
263                                 GDIPlus.CheckStatus (status);
264                         }
265                 }
266
267                 public Matrix Transform {
268                         get {
269                                 Matrix matrix = new Matrix ();
270                                 Status status = GDIPlus.GdipGetPathGradientTransform (NativeBrush, matrix.nativeMatrix);
271                                 GDIPlus.CheckStatus (status);
272
273                                 return matrix;
274                         }
275                         set {
276                                 if (value == null)
277                                         throw new ArgumentNullException ("Transform");
278
279                                 Status status = GDIPlus.GdipSetPathGradientTransform (NativeBrush, value.nativeMatrix);
280                                 GDIPlus.CheckStatus (status);
281                         }
282                 }
283
284                 public WrapMode WrapMode {
285                         get {
286                                 WrapMode wrapMode;
287                                 Status status = GDIPlus.GdipGetPathGradientWrapMode (NativeBrush, out wrapMode);
288                                 GDIPlus.CheckStatus (status);
289
290                                 return wrapMode;
291                         }
292                         set {
293                                 if ((value < WrapMode.Tile) || (value > WrapMode.Clamp))
294                                         throw new InvalidEnumArgumentException ("WrapMode");
295
296                                 Status status = GDIPlus.GdipSetPathGradientWrapMode (NativeBrush, value);
297                                 GDIPlus.CheckStatus (status);
298                         }
299                 }
300
301                 // Methods
302
303                 public void MultiplyTransform (Matrix matrix)
304                 {
305                         MultiplyTransform (matrix, MatrixOrder.Prepend);
306                 }
307
308                 public void MultiplyTransform (Matrix matrix, MatrixOrder order)
309                 {
310                         if (matrix == null)
311                                 throw new ArgumentNullException ("matrix");
312
313                         Status status = GDIPlus.GdipMultiplyPathGradientTransform (NativeBrush, matrix.nativeMatrix, order);
314                         GDIPlus.CheckStatus (status);
315                 }
316
317                 public void ResetTransform ()
318                 {
319                         Status status = GDIPlus.GdipResetPathGradientTransform (NativeBrush);
320                         GDIPlus.CheckStatus (status);
321                 }
322
323                 public void RotateTransform (float angle)
324                 {
325                         RotateTransform (angle, MatrixOrder.Prepend);
326                 }
327
328                 public void RotateTransform (float angle, MatrixOrder order)
329                 {
330                         Status status = GDIPlus.GdipRotatePathGradientTransform (NativeBrush, angle, order);
331                         GDIPlus.CheckStatus (status);
332                 }
333
334                 public void ScaleTransform (float sx, float sy)
335                 {
336                         ScaleTransform (sx, sy, MatrixOrder.Prepend);
337                 }
338
339                 public void ScaleTransform (float sx, float sy, MatrixOrder order)
340                 {
341                         Status status = GDIPlus.GdipScalePathGradientTransform (NativeBrush, sx, sy, order);
342                         GDIPlus.CheckStatus (status);
343                 }
344
345                 public void SetBlendTriangularShape (float focus)
346                 {
347                         SetBlendTriangularShape (focus, 1.0F);
348                 }
349
350                 public void SetBlendTriangularShape (float focus, float scale)
351                 {
352                         if (focus < 0 || focus > 1 || scale < 0 || scale > 1)
353                                 throw new ArgumentException ("Invalid parameter passed.");
354
355                         Status status = GDIPlus.GdipSetPathGradientLinearBlend (NativeBrush, focus, scale);
356                         GDIPlus.CheckStatus (status);
357                 }
358
359                 public void SetSigmaBellShape (float focus)
360                 {
361                         SetSigmaBellShape (focus, 1.0F);
362                 }
363
364                 public void SetSigmaBellShape (float focus, float scale)
365                 {
366                         if (focus < 0 || focus > 1 || scale < 0 || scale > 1)
367                                 throw new ArgumentException ("Invalid parameter passed.");
368
369                         Status status = GDIPlus.GdipSetPathGradientSigmaBlend (NativeBrush, focus, scale);
370                         GDIPlus.CheckStatus (status);
371                 }
372
373                 public void TranslateTransform (float dx, float dy)
374                 {
375                         TranslateTransform (dx, dy, MatrixOrder.Prepend);
376                 }
377
378                 public void TranslateTransform (float dx, float dy, MatrixOrder order)
379                 {
380                         Status status = GDIPlus.GdipTranslatePathGradientTransform (NativeBrush, dx, dy, order);
381                         GDIPlus.CheckStatus (status);
382                 }
383
384                 public override object Clone ()
385                 {
386                         IntPtr clonePtr;
387                         Status status = (Status) GDIPlus.GdipCloneBrush (new HandleRef(this, NativeBrush), out clonePtr);
388                         GDIPlus.CheckStatus (status);
389
390                         PathGradientBrush clone = new PathGradientBrush (clonePtr);
391                         return clone;
392                 }
393         }
394 }