# Paths

### Paths

In addition to using the basic shapes, you can compose and draw shapes together using a path. A path, modeled via the GraphicsPath class, is very much like a Graphics object, in that it's a logical container of zero or more shapes (called figures or subpaths). The main difference is that the figures can be started and ended arbitrarily.[7]

[7] Another important difference is that a Graphics object is backed by a surface such as a screen or a printer.

This means that you can compose one or more complicated figures from a set of basic shapes. You collect figures into a path so that you can frame or fill them as a unit using a single brush or pen, which is applied when the path is drawn. For example, Figure shows a rounded rectangle (a shape that the Graphics object can't draw for you directly).

##### 20. A Rounded Rectangle Composed of Arc Figures in a GraphicsPath Object

Imagine a method called GetRoundedRectPath that takes a rectangle and the radius of an arc describing the curve. Calling the function returns a path, which can be filled and framed using the Graphics methods FillPath and DrawPath:

```Graphics g = e.Graphics;
int width = this.ClientRectangle.Width;
int height = this.ClientRectangle.Height;
Rectangle rect = new Rectangle(10, 10, width - 20, height - 20);
using( GraphicsPath path = GetRoundedRectPath(rect, width / 10) ) {
g.FillPath(Brushes.Yellow, path);
g.DrawPath(Pens.Black, path);
}```

Even though the rounded rectangle path is composed of eight shapes (four arcs and four lines), the entire path is filled with one brush and framed with one pen. Here is the implementation of the method that composes the rounded rectangle:

```GraphicsPath GetRoundedRectPath(Rectangle rect, int radius) {
int diameter = 2 * radius;
Rectangle arcRect =
new Rectangle(rect.Location, new Size(diameter, diameter));

GraphicsPath path = new GraphicsPath();

// top left

// top right
arcRect.X = rect.Right - diameter;

// bottom right
arcRect.Y = rect.Bottom - diameter;

// bottom left
arcRect.X = rect.Left;

path.CloseFigure();

return path;
}```

This function adds four arcs to the pathone at each of the corners of the rectangle. Each shape added to the path is filled or framed as appropriate when the path is drawn or filled. In fact, notice that no pen or brush is used to add each shape. The pen or brush is provided when the path is drawn, and not when the shapes are added.

Also, notice that none of the lines are added explicitly. The first three lines are added implicitly by the path itself. As each new unclosed shape is added, the starting point of the new shape is joined to the ending point of the last unclosed shape, creating a connected figure. After the last arc is added, we call the CloseFigure method to join the ending point of that arc to the starting point of the first arc. If CloseFigure had not been called, we'd still have a closed figure when the path was filled and framed, but the line connecting the top-left arc with the bottom-left arc would be missing. On the other hand, adding a closed shape, such as a rectangle or an ellipse, will close itself, so there's no need to call CloseFigure.

If, after calling CloseFigure, we were to add another shape, then another figure would be started for us implicitly. If you'd like to start a new figure without closing the current figure, you can do so by calling StartFigure. Figure shows what would happen if StartFigure were called after the second arc at the top right is added to the path. Notice that there would be two figures in the path, the first one unclosed because the second figure was started without closing the first.

##### 21. Starting a New Figure in a Path Without Closing the Current Figure

Paths can add any of the shapes that the Graphics class can draw or fill. In fact, paths are handy because they can be used to create closed figures that aren't normally closed. For example, the following function returns a closed Bezier, another shape that the Graphics class doesn't provide directly:

```GraphicsPath GetClosedBezierPath(Rectangle rect, Point[] points) {
GraphicsPath path = new GraphicsPath();
path.CloseFigure();
return path;
}```

#### Fill Modes

When you compose a path of multiple figures that overlap, the overlap is subtractive by default. For example, the following code produces the donut in Figure:

##### 22. Figures That Overlap Completely Act Subtractively

```GraphicsPath GetDonutPath(Rectangle rect, int holeRadius) {
GraphicsPath path = new GraphicsPath();
Point centerPoint = new Point(...);
Rectangle holeRect = new Rectangle(...);
path.StartFigure(); // not needed: an ellipse will close itself