| ★ wanayoo — archive 1999 http://java.oreilly.com/bite-size/java_1198.html | Nouvelle recherche | Portail wanayoo |
|
||
|
|
The 2D API, in JDK 1.2, introduces the concept of paint. Paint is stuff you can use to fill shapes and text. Before the 2D API, you could only fill shapes and text with solid colors. Now, you can use any class that implements the java.awt.Paint interface. The 2D API offers three options:
To use one of these paints, just create it and give it to setPaint() on your Graphics2D. Any shapes or text that you render subsequently will use the new paint. To draw text in blue, for example, do this in a paint() method:
g2.setPaint(Color.blue); The 2D API's predefined paints are pretty cool. But you can write your own, too. In this column I'll develop a radial gradient paint. A radial gradient defines a color at a point; the gradient blends into another color as a function of the distance from that point. The end result is a big, fuzzy spot. Under the hoodHow does the Paint interface really work? Every Paint object has an associated context, a java.awt.PaintContext, which knows what colors to put on a drawing surface. When Graphics2D needs to fill a shape, it asks its current Paint for the corresponding PaintContext. Then it uses the PaintContext to actually put color on the drawing surface.Paint is a subinterface of Transparency, which describes the transparency mode of an object. The Paint interface itself has only one method -- it just knows how to generate a PaintContext: public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds, AffineTransform xform, RenderingHints hints) This method is called to create a PaintContext. The PaintContext is encouraged to produce colors in the given color model. The deviceBounds rectangle indicates the bounds of the drawing surface, while userBounds indicates the bounds of the shape that is being filled. The supplied AffineTransform indicates the transformation currently in effect, while hints contains information that the PaintContext can use to modify its behavior. The TexturePaint context, for example, is responsive to the KEY_INTERPOLATION hint.This may seem like a lot of unfamiliar stuff, but simple Paint implementations can ignore a lot of the parameters that are passed to createContext(), as you'll see in the upcoming example. The PaintContext returned by createContext() knows how to actually generate the colors of the Paint. The PaintContext interface defines three methods: public void dispose() This method is called when the PaintContext is no longer needed. If you've allocated any images or other large objects, you can free up their references in this method.public ColorModel getColorModel() This method returns the color model that will be used for this context's output. This could be a different color model than the one suggested in the createContext() method, back in the Paint interface.public Raster getRaster(int x, int y, int w, int h) This is the mother lode of the PaintContext interface. This method returns a Raster which contains the color data that should be used to fill a shape. (The Raster class is part of 2D's image classes.) The RoundGradientPaint ClassThe implementation consists of two classes, RoundGradientPaint and RoundGradientContext. RoundGradientPaint doesn't do much except return a RoundGradientPaintContext from its createContext() method. RoundGradientPaint's constructor accepts a point and a color that describe the center of the gradient, a radius, and a background color. The gradient blends color from the center point to the background color over the length of the radius. The parameters of the radial gradient are stored in appropriately-named member variables.
import java.awt.*;
public class RoundGradientPaint
public RoundGradientPaint(double x, double y, Color pointColor,
public PaintContext createContext(ColorModel cm,
public int getTransparency() { The getTransparency() method, from the Transparency interface, returns either OPAQUE or TRANSLUCENT, depending on the colors that were passed to RoundGradientPaint's constructor. If both colors are opaque, then the RoundGradientPaint is opaque too. Otherwise it is translucent, which means it may color pixels with arbitrary alpha values.
The RoundGradientContext ClassThe implementation of RoundGradientContext is straightforward. The getRaster() begins by creating a WritableRaster that will hold the color data generated for the radial gradient:
WritableRaster raster = Then this method iterates over each point in the requested rectangle, calculating the distance from the center point. It calculates a weighting factor, from 0.0 to 1.0, based on the ratio of this distance and the radius:
for (int j = 0; j < h; j++) { Then it simply uses the weighting factor to linearly interpolate between the center color and the background color:
data[base + 0] = (int)(mC1.getRed() + ratio *
The data is written into an array of integers. Each pixel is stored in four array elements, corresponding to red, green, blue, and alpha. When all the data has been written, the array is assigned to the WritableRaster as follows: raster.setPixels(0, 0, w, h, data); Here's the entire class:
import java.awt.*;
public RoundGradientContext(Point2D p, Color c1, double r, Color c2) {
public void dispose() {}
public ColorModel getColorModel() { return ColorModel.getRGBdefault(); }
public Raster getRaster(int x, int y, int w, int h) {
int[] data = new int[w * h * 4];
int base = (j * w + i) * 4;
Testing it OutHere's a simple class that demonstrates how you can use RoundGradientPaint to fill a round rectangle:
import java.awt.*;
public class RoundGradientTestFrame Most of the class has to do with plumbing -- setting up a Frame. The fun stuff is in the paint() method. A RoundGradientPaint is created and used to fill a round rectangle. Once you've done the work of writing RoundGradientPaint, it's very easy to use. Download the source code.
Jonathan Knudsen is a staff writer for O'Reilly & Associates. His first two books are Java Cryptography (availble now) and Java 2D (coming this winter). For a wealth of technical knowledge, visit O'Reilly's home page at http://www.oreilly.com/. Return to: java.oreilly.com
O'Reilly Home | O'Reilly Bookstores | How to Order | O'Reilly Contacts International | About O'Reilly | Affiliated Companies © 1998, O'Reilly & Associates, Inc. |
|