20.2. The Rendering Pipeline
One of the strengths of the 2D API is that shapes, text, and images are manipulated in many of the same ways. In this section, we'll describe what happens to shapes, text, and images after you give them to a Graphics2D object. Rendering is the process of taking some collection of shapes, text, and images and figuring out how to represent them by coloring pixels on a screen or printer. Graphics2D supports four rendering operations:
Draw a shape's outline with the draw( ) method.
Fill a shape's interior with the fill( ) method.
Draw some text with the drawString( ) method.
Draw an image with any of the many forms of the drawImage( ) method.
The graphics context represented by a Graphics2D object holds the following properties, whose values are controlled by corresponding accessor methods (e.g., getFont( ) and setFont( )):
The current paint (an object of type java.awt.Paint) determines what color or pattern will be used to fill a shape. This affects the drawing of shape outlines and text, as well. You can change the current paint using Graphics2D's setPaint( ) method. Note that the Color class implements the Paint interface, so you can pass Colors to setPaint( ) if you want to use solid colors.
Graphics2D uses the stroke to determine how to draw the outline of shapes that are passed to its draw( ) method. In graphics terminology, to "stroke" a shape means to take a path defined by the shape and effectively trace it with a pen or brush of a certain size and characteristics. For example, drawing the shape of a circle using a stroke that acts like a solid line would yield a washer or ring shape. The stroke object in the Graphics2D API is a little more abstract than that. In actuality it accepts the input shape to be stroked and returns an enclosed shape representing the outline, which Graphics2D then fills. You can set the current stroke using setStroke( ). The 2D API comes with a handy class, java.awt.BasicStroke, that implements different line widths, end styles, join styles, and dashing.
Text is rendered by creating a shape that represents the characters to be drawn. The current font determines what shapes are created for a given set of characters. The resulting text shape is then filled. The current font is set using setFont( ). The 2D API gives applications access to all the TrueType and PostScript Type 1 fonts that are installed.
Shapes, text, and images can be geometrically transformed before they are rendered. This means that they may be moved, rotated, and stretched. Graphics2D's transformation converts coordinates from "user space" to "device space." By default, Graphics2D uses a transformation that maps 72 units in user space to one inch on the output device. If you draw a line from point 0, 0 to point 72, 0 using the default transformation, it will be one inch long, regardless of whether it is drawn on your monitor or your printer. The current transformation can be modified using the translate( ), rotate( ), scale( ), and shear( ) methods.
A compositing rule determines how the colors of a new drawing operation are combined with existing colors on the Graphics2D's drawing surface. This attribute is set using setComposite( ), which accepts an instance of java.awt.AlphaComposite. Compositing allows you to make parts of a drawing or image completely or partially transparent, or to combine them in other interesting ways.
All rendering operations are limited to the interior of the clipping shape. No pixels outside this shape are modified. By default, the clipping shape allows rendering on the entire drawing surface (usually, the rectangular area of a Component). However, you can further limit this using any simple or complex shape (for example, text shapes).
There are different techniques that can be used to render graphics primitives. Usually these represent a tradeoff between rendering speed and visual quality or vice versa. Rendering hints (constants defined in the RenderingHints class) specify which techniques to use.
Graphics primitives (shapes, text, and images) pass through the rendering engine in a series of operations called the rendering pipeline. Let's walk through the pipeline. It can be reduced to four steps; the first step depends on the rendering operation:
Transform the shape. For shapes that will be filled, the shape is simply transformed using the Graphics2D's current transformation. For shapes whose outlines are drawn using draw( ), the current stroke is used to stroke the shape's outline. Then the stroked outline is transformed like any other filled shape. Text is displayed by mapping characters to shapes using the current font. The resulting text shapes are transformed like any other filled shape. Images are also transformed using the current transformation.
Determine the colors to be used. For a filled shape, the current paint object determines what colors should be used to fill the shape. For drawing an image, the colors are taken from the image itself.
Combine the colors with the existing drawing surface using the current compositing rule.
Clip the results using the current clipping shape.
The rendering hints are used throughout to control the rendering quality.