// RadialGradientContext.java package net.sf.gogui.boardpainter; import java.awt.Color; import java.awt.PaintContext; import java.awt.geom.Point2D; import java.awt.image.ColorModel; import java.awt.image.Raster; import java.awt.image.WritableRaster; /** Creates a raster with a radial color gradient. */ public class RadialGradientContext implements PaintContext { /** Create a radial gradient context. @param center The center point. @param radius1 The radius along the first axis of the ellipse. @param radius2 The radius along the second axis of the ellipse. @param focus Focus shift away from the center along second radius normalized to interval between zero and one. @param color1 First color. @param color2 Second color. */ public RadialGradientContext(Point2D center, Point2D radius1, Point2D radius2, double focus, Color color1, Color color2) { m_center = center; m_radius1 = radius1; m_radius2 = radius2; m_length1 = radius1.distance(0, 0); m_length2 = radius2.distance(0, 0); m_focus = focus; m_red1 = color1.getRed(); m_green1 = color1.getGreen(); m_blue1 = color1.getBlue(); m_alpha1 = color1.getAlpha(); m_redDiff = color2.getRed() - m_red1; m_greenDiff = color2.getGreen() - m_green1; m_blueDiff = color2.getBlue() - m_blue1; m_alphaDiff = color2.getAlpha() - m_alpha1; } public void dispose() { } public ColorModel getColorModel() { return ColorModel.getRGBdefault(); } public Raster getRaster(int x, int y, int width, int height) { if (m_raster != null && x == m_x && y == m_y && width == m_width && height == m_height) return m_raster; m_x = x; m_y = y; m_height = height; m_width = width; ColorModel colorModel = getColorModel(); m_raster = colorModel.createCompatibleWritableRaster(width, height); int[] data = new int[width * height * 4]; int index = -1; for (int j = 0; j < height; ++j) for (int i = 0; i < width; ++i) { Point2D p = new Point2D.Double(x + i, y + j); Point2D d = getDifference(p, m_center); double distance1 = getScalarProduct(d, m_radius1) / m_length1; double ratio1 = Math.abs(distance1) / m_length1; double distance2 = getScalarProduct(d, m_radius2) / m_length2; double ratio2 = distance2 / m_length2; if (ratio2 > m_focus) ratio2 = (ratio2 - m_focus) / (1.0 - m_focus); else ratio2 = (ratio2 - m_focus) / (-1.0 - m_focus); double ratio = Math.sqrt(ratio1 * ratio1 + ratio2 * ratio2); ratio = Math.min(ratio, 1.0); data[++index] = (int)(m_red1 + ratio * m_redDiff); data[++index] = (int)(m_green1 + ratio * m_greenDiff); data[++index] = (int)(m_blue1 + ratio * m_blueDiff); data[++index] = (int)(m_alpha1 + ratio * m_alphaDiff); } m_raster.setPixels(0, 0, width, height, data); return m_raster; } private final int m_red1; private final int m_redDiff; private final int m_green1; private final int m_greenDiff; private final int m_blue1; private final int m_blueDiff; private final int m_alpha1; private final int m_alphaDiff; private int m_x; private int m_y; private int m_height; private int m_width; private final double m_length1; private final double m_length2; private final double m_focus; private final Point2D m_center; private final Point2D m_radius1; private final Point2D m_radius2; private WritableRaster m_raster; private static Point2D getDifference(Point2D p1, Point2D p2) { return new Point2D.Double(p1.getX() - p2.getX(), p1.getY() - p2.getY()); } private static double getScalarProduct(Point2D p1, Point2D p2) { return (p1.getX() * p2.getX() + p1.getY() * p2.getY()); } }