/*******************************************************************************
* Breakout Cave Survey Visualizer
*
* Copyright (C) 2014 James Edwards
*
* jedwards8 at fastmail dot fm
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*******************************************************************************/
package org.breakout.awt;
import static org.andork.math3d.Vecmath.length;
import static org.andork.math3d.Vecmath.normalize2;
import static org.andork.math3d.Vecmath.setf;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.ColorModel;
import org.breakout.awt.MultipleGradientPaint.ColorSpaceType;
import org.breakout.awt.MultipleGradientPaint.CycleMethod;
public class ParamGradientMapPaintContext extends MultipleGradientPaintContext {
private final float[] origin = new float[2];
private float startParam, endParam;
private final float[] majorAxis = new float[2];
private final float[] minorAxis = new float[2];
/**
* Constructor for ParamGradientMapPaintContext.
*
* @param paint
* the {@code ParamGradientMapPaint} from which this context is
* created
* @param cm
* {@code ColorModel} that receives the <code>Paint</code> data.
* This is used only as a hint.
* @param deviceBounds
* the device space bounding box of the graphics primitive being
* rendered
* @param userBounds
* the user space bounding box of the graphics primitive being
* rendered
* @param t
* the {@code AffineTransform} from user space into device space
* (gradientTransform should be concatenated with this)
* @param hints
* the hints that the context object uses to choose between
* rendering alternatives
* @param dStart
* gradient start point, in user space
* @param dEnd
* gradient end point, in user space
* @param fractions
* the fractions specifying the gradient distribution
* @param colors
* the gradient colors
* @param cycleMethod
* either NO_CYCLE, REFLECT, or REPEAT
* @param colorSpace
* which colorspace to use for interpolation, either SRGB or
* LINEAR_RGB
*/
ParamGradientMapPaintContext(ParamGradientMapPaint paint,
ColorModel cm,
Rectangle deviceBounds,
Rectangle2D userBounds,
AffineTransform t,
RenderingHints hints,
float[] origin,
float[] majorAxis,
float[] minorAxis,
float startParam,
float endParam,
float[] fractions,
Color[] colors,
CycleMethod cycleMethod,
ColorSpaceType colorSpace) {
super(paint, cm, deviceBounds, userBounds, t, hints, fractions,
colors, cycleMethod, colorSpace);
float majorLength = length(majorAxis, 0, 2);
float minorLength = length(minorAxis, 0, 2);
setf(this.origin, origin);
normalize2(majorAxis, this.majorAxis);
normalize2(minorAxis, this.minorAxis);
this.majorAxis[0] /= majorLength;
this.majorAxis[1] /= majorLength;
this.minorAxis[0] /= minorLength * majorLength;
this.minorAxis[1] /= minorLength * majorLength;
this.startParam = startParam;
this.endParam = endParam;
}
/**
* Return a Raster containing the colors generated for the graphics
* operation. This is where the area is filled with colors distributed
* linearly.
*
* @param x
* ,y,w,h the area in device space for which colors are
* generated.
*/
@Override
protected void fillRaster(int[] pixels, int off, int adjust,
int x, int y, int w, int h) {
// TODO incorporate translation
for (int py = y; py < y + h; py++) {
for (int px = x; px < x + w; px++) {
float dx = px - origin[0];
float dy = py - origin[1];
float major = dx * majorAxis[0] + dy * majorAxis[1];
float minor = dx * minorAxis[0] + dy * minorAxis[1];
float param = startParam + (endParam - startParam) * (major + minor);
pixels[off++] = indexIntoGradientsArrays(param);
}
off += adjust;
}
}
}