/* | 
|
 * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. | 
|
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
|
 * | 
|
 * This code is free software; you can redistribute it and/or modify it | 
|
 * under the terms of the GNU General Public License version 2 only, as | 
|
 * published by the Free Software Foundation.  Oracle designates this | 
|
 * particular file as subject to the "Classpath" exception as provided | 
|
 * by Oracle in the LICENSE file that accompanied this code. | 
|
 * | 
|
 * This code 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 | 
|
 * version 2 for more details (a copy is included in the LICENSE file that | 
|
 * accompanied this code). | 
|
 * | 
|
 * You should have received a copy of the GNU General Public License version | 
|
 * 2 along with this work; if not, write to the Free Software Foundation, | 
|
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
|
 * | 
|
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
|
 * or visit www.oracle.com if you need additional information or have any | 
|
 * questions. | 
|
*/  | 
|
package java.awt;  | 
|
import java.awt.MultipleGradientPaint.CycleMethod;  | 
|
import java.awt.MultipleGradientPaint.ColorSpaceType;  | 
|
import java.awt.geom.AffineTransform;  | 
|
import java.awt.geom.Point2D;  | 
|
import java.awt.geom.Rectangle2D;  | 
|
import java.awt.image.ColorModel;  | 
|
/** | 
|
 * Provides the actual implementation for the LinearGradientPaint. | 
|
 * This is where the pixel processing is done. | 
|
 * | 
|
 * @see java.awt.LinearGradientPaint | 
|
 * @see java.awt.PaintContext | 
|
 * @see java.awt.Paint | 
|
 * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans | 
|
*/  | 
|
final class LinearGradientPaintContext extends MultipleGradientPaintContext {  | 
|
    /** | 
|
     * The following invariants are used to process the gradient value from | 
|
     * a device space coordinate, (X, Y): | 
|
     *     g(X, Y) = dgdX*X + dgdY*Y + gc | 
|
*/  | 
|
private float dgdX, dgdY, gc;  | 
|
    /** | 
|
     * Constructor for LinearGradientPaintContext. | 
|
     * | 
|
     * @param paint the {@code LinearGradientPaint} 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 start gradient start point, in user space | 
|
     * @param end 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 | 
|
*/  | 
|
LinearGradientPaintContext(LinearGradientPaint paint,  | 
|
ColorModel cm,  | 
|
Rectangle deviceBounds,  | 
|
Rectangle2D userBounds,  | 
|
AffineTransform t,  | 
|
RenderingHints hints,  | 
|
Point2D start,  | 
|
Point2D end,  | 
|
float[] fractions,  | 
|
Color[] colors,  | 
|
CycleMethod cycleMethod,  | 
|
ColorSpaceType colorSpace)  | 
|
    { | 
|
super(paint, cm, deviceBounds, userBounds, t, hints, fractions,  | 
|
colors, cycleMethod, colorSpace);  | 
|
// A given point in the raster should take on the same color as its  | 
|
// projection onto the gradient vector.  | 
|
// Thus, we want the projection of the current position vector  | 
|
// onto the gradient vector, then normalized with respect to the  | 
|
// length of the gradient vector, giving a value which can be mapped  | 
|
// into the range 0-1.  | 
|
// projection =  | 
|
// currentVector dot gradientVector / length(gradientVector)  | 
|
// normalized = projection / length(gradientVector)  | 
|
float startx = (float)start.getX();  | 
|
float starty = (float)start.getY();  | 
|
float endx = (float)end.getX();  | 
|
float endy = (float)end.getY();  | 
|
float dx = endx - startx; // change in x from start to end  | 
|
float dy = endy - starty; // change in y from start to end  | 
|
float dSq = dx*dx + dy*dy; // total distance squared  | 
|
        // avoid repeated calculations by doing these divides once | 
|
float constX = dx/dSq;  | 
|
float constY = dy/dSq;  | 
|
        // incremental change along gradient for +x | 
|
dgdX = a00*constX + a10*constY;  | 
|
        // incremental change along gradient for +y | 
|
dgdY = a01*constX + a11*constY;  | 
|
        // constant, incorporates the translation components from the matrix | 
|
gc = (a02-startx)*constX + (a12-starty)*constY;  | 
|
}  | 
|
    /** | 
|
     * 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. | 
|
*/  | 
|
protected void fillRaster(int[] pixels, int off, int adjust,  | 
|
int x, int y, int w, int h)  | 
|
    { | 
|
        // current value for row gradients | 
|
float g = 0;  | 
|
        // used to end iteration on rows | 
|
int rowLimit = off + w;  | 
|
        // constant which can be pulled out of the inner loop | 
|
float initConst = (dgdX*x) + gc;  | 
|
for (int i = 0; i < h; i++) { // for every row  | 
|
            // initialize current value to be start | 
|
g = initConst + dgdY*(y+i);  | 
|
while (off < rowLimit) { // for every pixel in this row  | 
|
                // get the color | 
|
pixels[off++] = indexIntoGradientsArrays(g);  | 
|
                // incremental change in g | 
|
g += dgdX;  | 
|
}  | 
|
            // change in off from row to row | 
|
off += adjust;  | 
|
            //rowlimit is width + offset | 
|
rowLimit = off + w;  | 
|
}  | 
|
}  | 
|
}  |