2 // System.Drawing.Drawing2D.PathGradientBrush.cs
5 // Dennis Hayes (dennish@Raytek.com)
6 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 // Ravindra (rkumar@novell.com)
9 // Copyright (C) 2002/3 Ximian, Inc. http://www.ximian.com
10 // Copyright (C) 2004,2006 Novell, Inc (http://www.novell.com)
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:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
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.
32 using System.ComponentModel;
33 using System.Runtime.InteropServices;
35 namespace System.Drawing.Drawing2D {
37 [MonoTODO ("libgdiplus/cairo doesn't support path gradients - unless it can be mapped to a radial gradient")]
38 public sealed class PathGradientBrush : Brush {
40 internal PathGradientBrush (IntPtr native)
42 SetNativeBrush (native);
45 public PathGradientBrush (GraphicsPath path)
48 throw new ArgumentNullException ("path");
51 Status status = GDIPlus.GdipCreatePathGradientFromPath (path.nativePath, out nativeObject);
52 GDIPlus.CheckStatus (status);
53 SetNativeBrush (nativeObject);
56 public PathGradientBrush (Point [] points) : this (points, WrapMode.Clamp)
60 public PathGradientBrush (PointF [] points) : this (points, WrapMode.Clamp)
64 public PathGradientBrush (Point [] points, WrapMode wrapMode)
67 throw new ArgumentNullException ("points");
68 if ((wrapMode < WrapMode.Tile) || (wrapMode > WrapMode.Clamp))
69 throw new InvalidEnumArgumentException ("WrapMode");
72 Status status = GDIPlus.GdipCreatePathGradientI (points, points.Length, wrapMode, out nativeObject);
73 GDIPlus.CheckStatus (status);
74 SetNativeBrush (nativeObject);
77 public PathGradientBrush (PointF [] points, WrapMode wrapMode)
80 throw new ArgumentNullException ("points");
81 if ((wrapMode < WrapMode.Tile) || (wrapMode > WrapMode.Clamp))
82 throw new InvalidEnumArgumentException ("WrapMode");
85 Status status = GDIPlus.GdipCreatePathGradient (points, points.Length, wrapMode, out nativeObject);
86 GDIPlus.CheckStatus (status);
87 SetNativeBrush (nativeObject);
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);
102 Blend blend = new Blend ();
103 blend.Factors = factors;
104 blend.Positions = positions;
109 // no null check, MS throws a NullReferenceException here
111 float [] factors = value.Factors;
112 float [] positions = value.Positions;
113 count = factors.Length;
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.");
118 if (count != positions.Length)
119 throw new ArgumentException ("Invalid Blend object. It should contain the same number of factors and positions values.");
121 if (positions [0] != 0.0F)
122 throw new ArgumentException ("Invalid Blend object. The positions array must have 0.0 as its first element.");
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.");
127 Status status = GDIPlus.GdipSetPathGradientBlend (NativeBrush, factors, positions, count);
128 GDIPlus.CheckStatus (status);
132 public Color CenterColor {
135 Status status = GDIPlus.GdipGetPathGradientCenterColor (NativeBrush, out centerColor);
136 GDIPlus.CheckStatus (status);
137 return Color.FromArgb (centerColor);
140 Status status = GDIPlus.GdipSetPathGradientCenterColor (NativeBrush, value.ToArgb ());
141 GDIPlus.CheckStatus (status);
145 public PointF CenterPoint {
148 Status status = GDIPlus.GdipGetPathGradientCenterPoint (NativeBrush, out center);
149 GDIPlus.CheckStatus (status);
154 PointF center = value;
155 Status status = GDIPlus.GdipSetPathGradientCenterPoint (NativeBrush, ref center);
156 GDIPlus.CheckStatus (status);
160 public PointF FocusScales {
164 Status status = GDIPlus.GdipGetPathGradientFocusScales (NativeBrush, out xScale, out yScale);
165 GDIPlus.CheckStatus (status);
167 return new PointF (xScale, yScale);
170 Status status = GDIPlus.GdipSetPathGradientFocusScales (NativeBrush, value.X, value.Y);
171 GDIPlus.CheckStatus (status);
175 public ColorBlend InterpolationColors {
178 Status status = GDIPlus.GdipGetPathGradientPresetBlendCount (NativeBrush, out count);
179 GDIPlus.CheckStatus (status);
180 // if no failure, then the "managed" minimum is 1
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
188 status = GDIPlus.GdipGetPathGradientPresetBlend (NativeBrush, intcolors, positions, count);
189 GDIPlus.CheckStatus (status);
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;
199 return interpolationColors;
202 // no null check, MS throws a NullReferenceException here
204 Color [] colors = value.Colors;
205 float [] positions = value.Positions;
206 count = colors.Length;
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.");
211 if (count != positions.Length)
212 throw new ArgumentException ("Invalid ColorBlend object. It should contain the same number of positions and color values.");
214 if (positions [0] != 0.0F)
215 throw new ArgumentException ("Invalid ColorBlend object. The positions array must have 0.0 as its first element.");
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.");
220 int [] blend = new int [colors.Length];
221 for (int i = 0; i < colors.Length; i++)
222 blend [i] = colors [i].ToArgb ();
224 Status status = GDIPlus.GdipSetPathGradientPresetBlend (NativeBrush, blend, positions, count);
225 GDIPlus.CheckStatus (status);
229 public RectangleF Rectangle {
232 Status status = GDIPlus.GdipGetPathGradientRect (NativeBrush, out rect);
233 GDIPlus.CheckStatus (status);
239 public Color [] SurroundColors {
242 Status status = GDIPlus.GdipGetPathGradientSurroundColorCount (NativeBrush, out count);
243 GDIPlus.CheckStatus (status);
245 int [] intcolors = new int [count];
246 status = GDIPlus.GdipGetPathGradientSurroundColorsWithCount (NativeBrush, intcolors, ref count);
247 GDIPlus.CheckStatus (status);
249 Color [] colors = new Color [count];
250 for (int i = 0; i < count; i++)
251 colors [i] = Color.FromArgb (intcolors [i]);
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 ();
262 Status status = GDIPlus.GdipSetPathGradientSurroundColorsWithCount (NativeBrush, colors, ref count);
263 GDIPlus.CheckStatus (status);
267 public Matrix Transform {
269 Matrix matrix = new Matrix ();
270 Status status = GDIPlus.GdipGetPathGradientTransform (NativeBrush, matrix.nativeMatrix);
271 GDIPlus.CheckStatus (status);
277 throw new ArgumentNullException ("Transform");
279 Status status = GDIPlus.GdipSetPathGradientTransform (NativeBrush, value.nativeMatrix);
280 GDIPlus.CheckStatus (status);
284 public WrapMode WrapMode {
287 Status status = GDIPlus.GdipGetPathGradientWrapMode (NativeBrush, out wrapMode);
288 GDIPlus.CheckStatus (status);
293 if ((value < WrapMode.Tile) || (value > WrapMode.Clamp))
294 throw new InvalidEnumArgumentException ("WrapMode");
296 Status status = GDIPlus.GdipSetPathGradientWrapMode (NativeBrush, value);
297 GDIPlus.CheckStatus (status);
303 public void MultiplyTransform (Matrix matrix)
305 MultiplyTransform (matrix, MatrixOrder.Prepend);
308 public void MultiplyTransform (Matrix matrix, MatrixOrder order)
311 throw new ArgumentNullException ("matrix");
313 Status status = GDIPlus.GdipMultiplyPathGradientTransform (NativeBrush, matrix.nativeMatrix, order);
314 GDIPlus.CheckStatus (status);
317 public void ResetTransform ()
319 Status status = GDIPlus.GdipResetPathGradientTransform (NativeBrush);
320 GDIPlus.CheckStatus (status);
323 public void RotateTransform (float angle)
325 RotateTransform (angle, MatrixOrder.Prepend);
328 public void RotateTransform (float angle, MatrixOrder order)
330 Status status = GDIPlus.GdipRotatePathGradientTransform (NativeBrush, angle, order);
331 GDIPlus.CheckStatus (status);
334 public void ScaleTransform (float sx, float sy)
336 ScaleTransform (sx, sy, MatrixOrder.Prepend);
339 public void ScaleTransform (float sx, float sy, MatrixOrder order)
341 Status status = GDIPlus.GdipScalePathGradientTransform (NativeBrush, sx, sy, order);
342 GDIPlus.CheckStatus (status);
345 public void SetBlendTriangularShape (float focus)
347 SetBlendTriangularShape (focus, 1.0F);
350 public void SetBlendTriangularShape (float focus, float scale)
352 if (focus < 0 || focus > 1 || scale < 0 || scale > 1)
353 throw new ArgumentException ("Invalid parameter passed.");
355 Status status = GDIPlus.GdipSetPathGradientLinearBlend (NativeBrush, focus, scale);
356 GDIPlus.CheckStatus (status);
359 public void SetSigmaBellShape (float focus)
361 SetSigmaBellShape (focus, 1.0F);
364 public void SetSigmaBellShape (float focus, float scale)
366 if (focus < 0 || focus > 1 || scale < 0 || scale > 1)
367 throw new ArgumentException ("Invalid parameter passed.");
369 Status status = GDIPlus.GdipSetPathGradientSigmaBlend (NativeBrush, focus, scale);
370 GDIPlus.CheckStatus (status);
373 public void TranslateTransform (float dx, float dy)
375 TranslateTransform (dx, dy, MatrixOrder.Prepend);
378 public void TranslateTransform (float dx, float dy, MatrixOrder order)
380 Status status = GDIPlus.GdipTranslatePathGradientTransform (NativeBrush, dx, dy, order);
381 GDIPlus.CheckStatus (status);
384 public override object Clone ()
387 Status status = (Status) GDIPlus.GdipCloneBrush (new HandleRef(this, NativeBrush), out clonePtr);
388 GDIPlus.CheckStatus (status);
390 PathGradientBrush clone = new PathGradientBrush (clonePtr);