grad
Class GradientPainter

java.lang.Object
  |
  +--java.util.Observable
        |
        +--grad.BasicGradientPainter
              |
              +--grad.GradientPainter
All Implemented Interfaces:
java.awt.image.ImageObserver, java.util.Observer, java.io.Serializable

public class GradientPainter
extends BasicGradientPainter
implements java.awt.image.ImageObserver, java.io.Serializable

GradientPainter is a class that accepts parameters defining a gradient, and can also paint the gradient into a Shape (actually, into the Shape's bounding box), and can also fill the gradient into an Image or just an array of pixel values.

This implementation can only paint several kinds of of gradients: linear gradients at any angle, conical gradients at any angle, square gradients at any angle, and radial gradients. The algorithm is fairly simple:

  1. for the given shape, get the bounding box as a rectangle (W,H)
  2. create a pixel array of (WxH)
  3. For each pixel in that array:
    1. Translate the point by (-W/2,-H/2)
    2. Rotate the point by the given angle
    3. Compute the color at that point in the simple version of the gradient
    4. Put the color into the array.
  4. Create an Image from the pixel array using MemoryImageSource
  5. Draw the image using Graphics.drawImage

The image is cached for later use; each GradientPainter object will cache exactly one Image. [This way, if you use a separate GradientPainter for each region you wish to paint then the first paint call will be slow but subsequent ones will be very fast, at the cost of hogging more memory for caching.]

A gradient can be a simple gradient, defined by a start and end color, or it can be a multi-part gradient composed of several GradientSegments.

The usual sequence for using this class is:

  1. Create the GradientPainter
  2. Add one or more segments
  3. Paint a gradient into a Shape
Then you would do step 3 repeatedly.

Internally, the GradientPainter holds its list of segments on a Vector and uses them in sequence. It is the responsibility of the caller to ensure that the segments link up correctly. Regions of the range [0.0..1.0] that have noo segment corresponding to them will be painted with the background color. Regions that overlap will be painted with the lowest-numbered segment that applies to them.

This class supports Java 1.1 and Java 2. Under Java 1.1 the Shape to paint may be a Rectangle or a Polygon or any other shape supported by java.awt.Graphics.setClip(), [which is usually just Rectangle; the code uses a hideous kludge to auto-recognize this piece of Java1.1-lameness and work around it by making parts of the image transparent, ack!]. Under Java 2, it supports any Shape that can be used to clip with a Graphics2D, include Ellipse2D and GeneralPath. Eventually, I hope to support the full Java2D Paint interface with a separate FancyGradientPaint class.

Objects of class GradientPainter serve as Observables, so that other objects interested in knowing when the gradient has changed (and therefore needs to be repainted) can register themselves as Observers.

See Also:
GradientSegment, Shape, Serialized Form

Field Summary
protected  java.awt.Color bg
           
protected  int cacheAngle
           
protected  java.awt.Point cacheBasePoint
           
protected  java.awt.Rectangle cacheBaseRect
           
protected  int cacheDefRGB
           
protected  int cacheExtent
           
protected  java.awt.Polygon cacheHackClipShape
           
protected  java.awt.Image cacheImage
           
protected  int cacheMode
           
static int CONICAL_GRADIENT
          A conical gradient pointing, by default, to the center right.
protected  int defAngle
           
protected  java.awt.Point defCenter
           
protected  int defExtent
           
protected  double exf
           
protected  int glim
           
protected  java.awt.Polygon hackClipShape
           
static int LINEAR_GRADIENT
          Linear gradient, by default painted from along the x axis left to right.
static int RADIAL_GRADIENT
          A radial gradient with the center at the center of the Shape bounding box.
static int SQUARE_GRADIENT
          A square gradient with the center at the center of the Shape bounding box.
protected  double th
           
protected  int tmode
           
protected  double tw
           
protected  double tx
           
protected  double ty
           
protected  double xrx
           
protected  double xry
           
protected  double yrx
           
protected  double yry
           
 
Fields inherited from class grad.BasicGradientPainter
DEFAULT_MODE, master, segments
 
Fields inherited from interface java.awt.image.ImageObserver
ABORT, ALLBITS, ERROR, FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, WIDTH
 
Constructor Summary
GradientPainter()
          Create a new GradientPainter with 0 segments.
GradientPainter(BasicGradientPainter src)
          Create a GradientPainter with the same segments as the supplied BasicGradientPainter.
GradientPainter(java.awt.Color c1, java.awt.Color c2)
          Create a simple GradientPainter with 1 simple RGB segment.
 
Method Summary
protected  int computeColorFor(double x, double y)
          Compute the color for a given point and return it.
 java.awt.Image computeGradientImage(java.awt.Toolkit tk, java.awt.Rectangle baserect, java.awt.Point basepoint, int ext, int angle, int mode, int defrgb)
          Get an image with the requested gradient in it.
 void computeGradientPixels(int w, int h, int[] pixels, java.awt.Point basepoint, int ext, int angle, int mode, int defrgb)
          Fill the pixel array for a given gradient.
 java.awt.Color getBackground()
          Retrieve the default background color.
 int getDefaultAngle()
          Retreive the default angle.
 java.awt.Point getDefaultCenter()
          Retreive the default center point.
 int getDefaultExtent()
          Retreive the default angle.
 void gradientsChanged()
          Invalidate the cached image, if any, because the GradientSegments have been changed somehow.
 boolean imageUpdate(java.awt.Image im, int info, int x, int y, int w, int h)
          Do-nothing version of imageUpdate to allow this object to be used as a lazy imageObserver
 void paint(java.awt.Graphics g, java.awt.Shape s, int mode)
          Paint a gradient into a given Shape using a given Graphics.
 void paint(java.awt.Graphics g, java.awt.Shape s, java.awt.Point center, int extent, int angle, int mode)
          Paint a gradient into a given Shape area using a given Graphics.
 void setBackground(java.awt.Color c)
          Set the default background color; this is the color that will be used where no segment applies.
 void setDefaultAngle(int angle)
          Set default values for the angle, normally 0.
 void setDefaultCenter(java.awt.Point pt)
          Set default center point for the gradient drawing.
 void setDefaultExtent(int extent)
          Set default values for the extent, which is normally auto-computed from the size of the paint region.
 
Methods inherited from class grad.BasicGradientPainter
addSegment, countSegments, flipSegment, getSegment, removeSegment, setSegment, slaveTo, splitSegment, swapAt, toCodeFragment, toString, update
 
Methods inherited from class java.util.Observable
addObserver, clearChanged, countObservers, deleteObserver, deleteObservers, hasChanged, notifyObservers, notifyObservers, setChanged
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

LINEAR_GRADIENT

public static final int LINEAR_GRADIENT
Linear gradient, by default painted from along the x axis left to right. Use a different angle to get a gradient along some other axis. For simple vertical or horizontal gradients, use LinearGradientPainter instead.
See Also:
LinearGradientPainter

CONICAL_GRADIENT

public static final int CONICAL_GRADIENT
A conical gradient pointing, by default, to the center right. The extent value does not matter for conical gradients.

RADIAL_GRADIENT

public static final int RADIAL_GRADIENT
A radial gradient with the center at the center of the Shape bounding box. The angle value does not matter for radial gradients.

SQUARE_GRADIENT

public static final int SQUARE_GRADIENT
A square gradient with the center at the center of the Shape bounding box. At this time, we can only do squares; maybe someday we will also have rectanglar gradients.

bg

protected java.awt.Color bg

defAngle

protected int defAngle

defExtent

protected int defExtent

defCenter

protected java.awt.Point defCenter

cacheImage

protected transient java.awt.Image cacheImage

cacheBaseRect

protected transient java.awt.Rectangle cacheBaseRect

cacheAngle

protected transient int cacheAngle

cacheBasePoint

protected transient java.awt.Point cacheBasePoint

cacheMode

protected transient int cacheMode

cacheExtent

protected transient int cacheExtent

cacheDefRGB

protected transient int cacheDefRGB

cacheHackClipShape

protected transient java.awt.Polygon cacheHackClipShape

hackClipShape

protected transient java.awt.Polygon hackClipShape

xrx

protected transient double xrx

xry

protected transient double xry

yrx

protected transient double yrx

yry

protected transient double yry

tx

protected transient double tx

ty

protected transient double ty

tw

protected transient double tw

th

protected transient double th

exf

protected transient double exf

glim

protected transient int glim

tmode

protected transient int tmode
Constructor Detail

GradientPainter

public GradientPainter(java.awt.Color c1,
                       java.awt.Color c2)
Create a simple GradientPainter with 1 simple RGB segment.

GradientPainter

public GradientPainter(BasicGradientPainter src)
Create a GradientPainter with the same segments as the supplied BasicGradientPainter. This is basically a copy constructor.

GradientPainter

public GradientPainter()
Create a new GradientPainter with 0 segments.
Method Detail

setBackground

public void setBackground(java.awt.Color c)
Set the default background color; this is the color that will be used where no segment applies.

getBackground

public java.awt.Color getBackground()
Retrieve the default background color.

paint

public void paint(java.awt.Graphics g,
                  java.awt.Shape s,
                  int mode)
Paint a gradient into a given Shape using a given Graphics. Note that you can use any Shape, including a Rectangle or a Polygon. If Shape is null, then uses the current clip shape of the Graphics. Mode must be one of the constants LINEAR_GRADIENT, CONICAL_GRADIENT, RADIAL_GRADIENT, or SQUARE_GRADIENT.
Overrides:
paint in class BasicGradientPainter
Following copied from class: grad.BasicGradientPainter
Parameters:
g - Graphics to paint into
s - Shape to fill (usually a Rectangle)
mode - Gradient generation mode (defined per subclass)

setDefaultAngle

public void setDefaultAngle(int angle)
Set default values for the angle, normally 0. This will be used when the simple 3-argument version of paint() is called. If the new default is different from the previous one, then the observers are notified.
Parameters:
angle - The default angle to use, in degrees

getDefaultAngle

public int getDefaultAngle()
Retreive the default angle.

setDefaultExtent

public void setDefaultExtent(int extent)
Set default values for the extent, which is normally auto-computed from the size of the paint region. This will be used when the simple 3-argument version of paint() is called. If the new default is different from the previous one, then the observers are notified. Pass 0 to return to the default behavior of autocomputing the extent from the shape.
Parameters:
angle - The default extent to use, >1

getDefaultExtent

public int getDefaultExtent()
Retreive the default angle.

setDefaultCenter

public void setDefaultCenter(java.awt.Point pt)
Set default center point for the gradient drawing. This will be used when the simple 3-argument version of paint() is called. If the new default is different from the previous one, then the observers are notified. If no default center is set, or the default is set to null, then a new center point will be autocomputed from the shape at each call of the 3-argument version of paint().
Parameters:
pt - Default center point to use (absolute!)

getDefaultCenter

public java.awt.Point getDefaultCenter()
Retreive the default center point.

paint

public void paint(java.awt.Graphics g,
                  java.awt.Shape s,
                  java.awt.Point center,
                  int extent,
                  int angle,
                  int mode)
Paint a gradient into a given Shape area using a given Graphics. The center Point should normally be within the bounds of the Shape s. The extent is the overall size of the gradient; For a radial or square gradient, it is usually the radius of the Shape s, for a linear gradient it is usually the size of the shape along the given angle, for a conical gradient extent doesn't matter. Note that the extent must be large enough so that the gradient covers the whole shape even if the center is offset. If the center is null, then it will be set to the center of the Shape's bounding box. The angle must be in degrees; 0 degrees is pointing horizontally to the right. Mode must be one of the constants LINEAR_GRADIENT, CONICAL_GRADIENT, RADIAL_GRADIENT, or SQUARE_GRADIENT.
Parameters:
g - Graphics into which to paint
s - Shape of the area to paint (usually rectangular)
center - The center of the gradient (or null)
extent - Size of the gradient computation (>1)
angle - Angle of the gradient computation
mode - Kind of gradient to paint (default: Linear)

computeGradientImage

public java.awt.Image computeGradientImage(java.awt.Toolkit tk,
                                           java.awt.Rectangle baserect,
                                           java.awt.Point basepoint,
                                           int ext,
                                           int angle,
                                           int mode,
                                           int defrgb)
Get an image with the requested gradient in it. This method is used by the paint() method, and it may also be called directly. It has a lot of parameters.
Parameters:
tk - The AWT toolkit to use, typically from Component.getToolkit()
baserect - A rectangle at origin 0,0 - gives the size of the image
center - The centerpoint of the gradient (from origin 0,0)
ext - Extent of the gradient, usually related to size of image
angle - Angle of the gradient in degrees
mode - Kind of gradient to paint
defrgb - Color to use where the gradient doesnt paint

computeGradientPixels

public void computeGradientPixels(int w,
                                  int h,
                                  int[] pixels,
                                  java.awt.Point basepoint,
                                  int ext,
                                  int angle,
                                  int mode,
                                  int defrgb)
Fill the pixel array for a given gradient. This is the most primitive of the public methods, but it can be used to support the Java2 Raster/DataBuffer/Paint architecture. Note that, when you would call this from elsewhere, you
Parameters:
w - Width of the raster to fill in with pixels
h - Height of the raster to fill in with pixels
pixels - Array of ints, w*h in size
basepoint - Base point for the clipping region (usually null)
ext - Extent of the gradient (very important, must be >1)
angle - Angle of the gradient in degrees (ignored for Radial)
mode - Gradient mode, linear, radial, conical, square
defrgb - raw sRGB int color to use for unpainted areas

computeColorFor

protected final int computeColorFor(double x,
                                    double y)
Compute the color for a given point and return it. Most of the data gets passed in as protected member variables, for speed.

gradientsChanged

public void gradientsChanged()
Invalidate the cached image, if any, because the GradientSegments have been changed somehow. You must call this if you've changed one of the segments by calling any of the GradientSegment setXXX methods. This implementation calls BasicGradientPainter's gradientsChanged() method too, so that we take care of notifying any observers.
Overrides:
gradientsChanged in class BasicGradientPainter

imageUpdate

public boolean imageUpdate(java.awt.Image im,
                           int info,
                           int x,
                           int y,
                           int w,
                           int h)
Do-nothing version of imageUpdate to allow this object to be used as a lazy imageObserver
Specified by:
imageUpdate in interface java.awt.image.ImageObserver