
Using the PathGradientBrushOne of the more interesting capabilities of GDI+ is the way you can control colour using the various brushes. The PathGradientBrush enables you to create very impressive areas of colour that change subtly over an area defined by a path. Figure1 shows a rectangle filled with a PathGradientBrush.
Figure 1. A rectangle filled with a PathGradientBrush You may be saying to yourself right now "Bob's cracked. The strain is too much for him. Anyone can see that's a triangle" but in fact, the statement is perfectly correct. The code that created this effect is shown in listing 1. You can clearly see that the fill is rectangular. This illustrates that the brush has a particular shape and will not fill outside of the specified area. This means that a PathGradientBrush needs to be carefully constructed otherwise discontinuities in the colours will be seen where the brush edge ends. Listing 1. PathGradientBrush pgb=new PathGradientBrush(new Point[]{ new Point(this.ClientRectangle.Width/2,0), new Point(0,this.ClientRectangle.Height), new Point(this.ClientRectangle.Width,this.ClientRectangle.Height)});
pgb.SurroundColors=new Color[]{Color.Red, Color.Green, Color.Blue};
pgb.CenterColor=Color.Gray;
e.Graphics.FillRectangle(pgb,this.ClientRectangle);
pgb.Dispose();
Got them surroundedThe brush defined in listing 1 uses a central point that's defined as gray in colour and a set of points that define the vertices of the triangle. The path is defined implicitly by the array of points passed to the constructor and so the number of colours and their complexity can be as complex as you wish. The surround colours can have a 1:1 correlation to all the points in the path or may only affect a few of them. The rule is that SurroundColors will be matched to each point in the path until there are no more colours left. Then the last colour in SurroundColors is used for all the rest. Figure 2 shows an ellipse which has many vertices around it's edge matched with surround colours that only define the seven colours of the rainbow.
Figure 2. Many vertices, few colours. Listing 2. GraphicsPath pth=new GraphicsPath(); pth.AddEllipse(this.ClientRectangle); PathGradientBrush pgb=new PathGradientBrush(pth); pgb.SurroundColors=new Color[]{ Color.Red, Color.Orange, Color.Yellow, Color.Green, Color.Blue, Color.Indigo, Color.Violet }; pgb.CenterColor=Color.Gray; e.Graphics.FillRectangle(pgb,this.ClientRectangle);
A lot of ballsDespite its ability to create really complex colour washes, the PathGradientBrush is possibly most useful in it's simplest mode for putting a shine on something. This kind of effect can make the difference between a flat and uninteresting graphic and one that almost looks 3D. The image in Figure 3 was created using a simple offset of the CenterColor property to provide a spherical shading.
Figure 3. Simple but effective spherical shading. Listing 3. Color[] SnookerBalls=new Color[]{ Color.Yellow, Color.Brown, Color.Green, Color.Blue, Color.Magenta, Color.Red, Color.Red, Color.Red, Color.Red, Color.Red, Color.Red, Color.Red, Color.Red, Color.Red, Color.Red, Color.Red, Color.Red, Color.Red, Color.Red, Color.Red, Color.Black};
PointF[] pts=new PointF[]{ new PointF(10,10), new PointF(20,10), new PointF(30,10), new PointF(20,25), new PointF(20,36), new PointF(20,38), new PointF(18,40), new PointF(22,40), new PointF(16,42), new PointF(20,42), new PointF(24,42), new PointF(14,44), new PointF(18,44), new PointF(22,44), new PointF(26,44), new PointF(12,46), new PointF(16,46), new PointF(20,46), new PointF(24,46), new PointF(28,46), new PointF(20,58)};
e.Graphics.SmoothingMode=SmoothingMode.AntiAlias;
GraphicsPath pth=new GraphicsPath(); pth.AddEllipse(-2f,-2f,4f,4f); PathGradientBrush pgb=new PathGradientBrush(pth);
for(int x=0;x<21;x++) { pgb.CenterColor=Color.White; pgb.CenterPoint=new PointF(-1.5f,-1.5f); pgb.SurroundColors=new Color[]{SnookerBalls[x]}; e.Graphics.Transform=new Matrix(10,0,0,10,10*pts[x].X,10*pts[x].Y); e.Graphics.FillEllipse(pgb,-2f,-2f,4f,4f); }
pgb.Dispose();
Blending inAs you may have seen in the LinearGradientBrush article, the PathGradientBrush can modify the way that colours change by applying a blend. In the case of linear gradients the blend enables you to modify the intensity of colour from one end of the gradient to the other. The PathGradientBrush does the same action but from the centre-point to the surround points. Figure 4 shows how a blend affects the PathGradientBrush. Listing 4 shows the code that created this effect.
Figure 4. Listing 4. PointF[] p=new PointF[11]; float t; bool i; int n; for(t=0, i=false, n=0; t<=(Math.PI*2); t+=(float)Math.PI/5, i=!i, n++) { float l=50+(80*(i ? 0 : 1)); p[n]=new PointF((float)Math.Cos(t-Math.PI/2)*l,(float)Math.Sin(t-Math.PI/2)*l); } p[n]=p[0];
GraphicsPath pth=new GraphicsPath();
pth.AddLines(p);
PathGradientBrush pgb=new PathGradientBrush(pth);
pgb.CenterColor=Color.White; pgb.SurroundColors=new Color[]{Color.Black}; Blend b=new Blend(); b.Factors=new float[]{1,0,1,0,1}; b.Positions=new float[]{0,0.25f,0.5f,0.75f,1f};
pgb.Blend=b;
e.Graphics.Transform=new Matrix(1,0,0,1,this.ClientSize.Width/2,this.ClientSize.Height/2);
e.Graphics.FillPath(pgb,pth); The PathGradientBrush also has methods to set a sigma bell-curve and a triangular shaped blend. Colour blending.Just as a ColorBlend object can be applied to a LinearGradientBrush, so to can the same technique be used to create amazing colour fills for complex shapes. Figure 5 shows the star filled with the old favourite rainbow blend.
Figure 5. ColorBlend and PathGradientBrush. Listing 6. ColorBlend cb=new ColorBlend(7); int c; float f; for(f=0, c=0;f<=1;f+=1.0f/6, c++) cb.Positions[c]=f; cb.Colors=new Color[]{ Color.Red, Color.Orange, Color.Yellow, Color.Green, Color.Blue, Color.Indigo, Color.Violet}; pgb.InterpolationColors=cb; pgb.FocusScales=new PointF(0.5f,0.3f);
e.Graphics.Transform=new Matrix(1,0,0,1,this.ClientSize.Width/2,this.ClientSize.Height/2);
e.Graphics.FillPath(pgb,pth);
Focus ScalesThe colour changes in the PathGradientBrush usually start at outside and work in towards the central or offset focus point. One way of making this display less linear is to brovide a blend but PathGradientBrush also provides the FocusScales property that enables you to move the distance of the final colour transition away from the focus point. The FocusScales property takes a PointF with X and Y values that range between 0 and 1 which move the point of the final colour transition to a percentage of the overall distance between edge and focus. The cameo border shown in figure 6 and the listing which follows show how the focus area has been enlarged to 0.8 times the distance between the focal point and the edge of the brush.
Figure 6. FocusScales at work. Listing 6. GraphicsPath pth=new GraphicsPath(); pth.AddEllipse(50,50,300,500); PathGradientBrush pgb=new PathGradientBrush(pth); pgb.CenterColor=Color.Red; pgb.SurroundColors=new Color[]{Color.White}; pgb.FocusScales=new PointF(0.8f,0.8f); e.Graphics.FillEllipse(pgb,50,50,300,500);
Copyright Robert W. Powell 2004. All rights reserved.
|