FileDocCategorySizeDatePackage
GradientPaintContext.javaAPI DocJava SE 5 API7513Fri Aug 26 14:56:44 BST 2005java.awt

GradientPaintContext

public class GradientPaintContext extends Object implements PaintContext

Fields Summary
static ColorModel
xrgbmodel
static ColorModel
xbgrmodel
static ColorModel
cachedModel
static WeakReference
cached
double
x1
double
y1
double
dx
double
dy
boolean
cyclic
int[]
interp
Raster
saved
ColorModel
model
Constructors Summary
public GradientPaintContext(ColorModel cm, Point2D p1, Point2D p2, AffineTransform xform, Color c1, Color c2, boolean cyclic)

	// First calculate the distance moved in user space when
	// we move a single unit along the X & Y axes in device space.
	Point2D xvec = new Point2D.Double(1, 0);
	Point2D yvec = new Point2D.Double(0, 1);
	try {
	    AffineTransform inverse = xform.createInverse();
	    inverse.deltaTransform(xvec, xvec);
	    inverse.deltaTransform(yvec, yvec);
	} catch (NoninvertibleTransformException e) {
	    xvec.setLocation(0, 0);
	    yvec.setLocation(0, 0);
	}

	// Now calculate the (square of the) user space distance
	// between the anchor points. This value equals:
	//     (UserVec . UserVec)
	double udx = p2.getX() - p1.getX();
	double udy = p2.getY() - p1.getY();
	double ulenSq = udx * udx + udy * udy;

	if (ulenSq <= Double.MIN_VALUE) {
	    dx = 0;
	    dy = 0;
	} else {
	    // Now calculate the proportional distance moved along the
	    // vector from p1 to p2 when we move a unit along X & Y in
	    // device space.
	    //
	    // The length of the projection of the Device Axis Vector is
	    // its dot product with the Unit User Vector:
	    //     (DevAxisVec . (UserVec / Len(UserVec))
	    //
	    // The "proportional" length is that length divided again
	    // by the length of the User Vector:
	    //     (DevAxisVec . (UserVec / Len(UserVec))) / Len(UserVec)
	    // which simplifies to:
	    //     ((DevAxisVec . UserVec) / Len(UserVec)) / Len(UserVec)
	    // which simplifies to:
	    //     (DevAxisVec . UserVec) / LenSquared(UserVec)
	    dx = (xvec.getX() * udx + xvec.getY() * udy) / ulenSq;
	    dy = (yvec.getX() * udx + yvec.getY() * udy) / ulenSq;

	    if (cyclic) {
		dx = dx % 1.0;
		dy = dy % 1.0;
	    } else {
		// We are acyclic
		if (dx < 0) {
		    // If we are using the acyclic form below, we need
		    // dx to be non-negative for simplicity of scanning
		    // across the scan lines for the transition points.
		    // To ensure that constraint, we negate the dx/dy
		    // values and swap the points and colors.
		    Point2D p = p1; p1 = p2; p2 = p;
		    Color c = c1; c1 = c2; c2 = c;
		    dx = -dx;
		    dy = -dy;
		}
	    }
	}

	Point2D dp1 = xform.transform(p1, null);
	this.x1 = dp1.getX();
	this.y1 = dp1.getY();

	this.cyclic = cyclic;
	int rgb1 = c1.getRGB();
	int rgb2 = c2.getRGB();
	int a1 = (rgb1 >> 24) & 0xff;
	int r1 = (rgb1 >> 16) & 0xff;
	int g1 = (rgb1 >>  8) & 0xff;
	int b1 = (rgb1      ) & 0xff;
	int da = ((rgb2 >> 24) & 0xff) - a1;
	int dr = ((rgb2 >> 16) & 0xff) - r1;
	int dg = ((rgb2 >>  8) & 0xff) - g1;
	int db = ((rgb2      ) & 0xff) - b1;
	if (a1 == 0xff && da == 0) {
	    model = xrgbmodel;
	    if (cm instanceof DirectColorModel) {
		DirectColorModel dcm = (DirectColorModel) cm;
		int tmp = dcm.getAlphaMask();
		if ((tmp == 0 || tmp == 0xff) &&
		    dcm.getRedMask() == 0xff &&
		    dcm.getGreenMask() == 0xff00 &&
		    dcm.getBlueMask() == 0xff0000)
		{
		    model = xbgrmodel;
		    tmp = r1; r1 = b1; b1 = tmp;
		    tmp = dr; dr = db; db = tmp;
		}
	    }
	} else {
	    model = ColorModel.getRGBdefault();
	}
	interp = new int[cyclic ? 513 : 257];
	for (int i = 0; i <= 256; i++) {
	    float rel = i / 256.0f;
	    int rgb =
		(((int) (a1 + da * rel)) << 24) |
		(((int) (r1 + dr * rel)) << 16) |
		(((int) (g1 + dg * rel)) <<  8) |
		(((int) (b1 + db * rel))      );
	    interp[i] = rgb;
	    if (cyclic) {
		interp[512 - i] = rgb;
	    }
	}
    
Methods Summary
voidclipFillRaster(int[] pixels, int off, int adjust, int w, int h, double rowrel, double dx, double dy)

	while (--h >= 0) {
	    double colrel = rowrel;
	    int j = w;
	    if (colrel <= 0.0) {
		int rgb = interp[0];
		do {
		    pixels[off++] = rgb;
		    colrel += dx;
		} while (--j > 0 && colrel <= 0.0);
	    }
	    while (colrel < 1.0 && --j >= 0) {
		pixels[off++] = interp[(int) (colrel * 256)];
		colrel += dx;
	    }
	    if (j > 0) {
		int rgb = interp[256];
		do {
		    pixels[off++] = rgb;
		} while (--j > 0);
	    }

	    off += adjust;
	    rowrel += dy;
        }
    
voidcycleFillRaster(int[] pixels, int off, int adjust, int w, int h, double rowrel, double dx, double dy)

	rowrel = rowrel % 2.0;
	int irowrel = ((int) (rowrel * (1 << 30))) << 1;
	int idx = (int) (-dx * (1 << 31));
	int idy = (int) (-dy * (1 << 31));
	while (--h >= 0) {
	    int icolrel = irowrel;
	    for (int j = w; j > 0; j--) {
		pixels[off++] = interp[icolrel >>> 23];
		icolrel += idx;
	    }

	    off += adjust;
	    irowrel += idy;
        }
    
public voiddispose()
Release the resources allocated for the operation.

	if (saved != null) {
	    putCachedRaster(model, saved);
	    saved = null;
	}
    
static synchronized java.awt.image.RastergetCachedRaster(java.awt.image.ColorModel cm, int w, int h)


             
	if (cm == cachedModel) {
	    if (cached != null) {
		Raster ras = (Raster) cached.get();
		if (ras != null &&
		    ras.getWidth() >= w &&
		    ras.getHeight() >= h)
		{
		    cached = null;
		    return ras;
		}
	    }
	}
	return cm.createCompatibleWritableRaster(w, h);
    
public java.awt.image.ColorModelgetColorModel()
Return the ColorModel of the output.

        return model;
    
public java.awt.image.RastergetRaster(int x, int y, int w, int h)
Return a Raster containing the colors generated for the graphics operation.

param
x,y,w,h The area in device space for which colors are generated.

	double rowrel = (x - x1) * dx + (y - y1) * dy;

	Raster rast = saved;
	if (rast == null || rast.getWidth() < w || rast.getHeight() < h) {
	    rast = getCachedRaster(model, w, h);
	    saved = rast;
	}
	IntegerComponentRaster irast = (IntegerComponentRaster) rast;
	int off = irast.getDataOffset(0);
	int adjust = irast.getScanlineStride() - w;
	int[] pixels = irast.getDataStorage();

	if (cyclic) {
	    cycleFillRaster(pixels, off, adjust, w, h, rowrel, dx, dy);
	} else {
	    clipFillRaster(pixels, off, adjust, w, h, rowrel, dx, dy);
	}

	return rast;
    
static synchronized voidputCachedRaster(java.awt.image.ColorModel cm, java.awt.image.Raster ras)

	if (cached != null) {
	    Raster cras = (Raster) cached.get();
	    if (cras != null) {
		int cw = cras.getWidth();
		int ch = cras.getHeight();
		int iw = ras.getWidth();
		int ih = ras.getHeight();
		if (cw >= iw && ch >= ih) {
		    return;
		}
		if (cw * ch >= iw * ih) {
		    return;
		}
	    }
	}
	cachedModel = cm;
	cached = new WeakReference(ras);