/*
* 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 com.sun.prism.j2d.paint;
import java.awt.Color;
import java.awt.Paint;
import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel;
import java.lang.ref.SoftReference;
This is the superclass for Paints which use a multiple color gradient to fill in their raster. It provides storage for variables and enumerated values common to LinearGradientPaint
and RadialGradientPaint
. /**
* This is the superclass for Paints which use a multiple color
* gradient to fill in their raster. It provides storage for variables and
* enumerated values common to
* {@code LinearGradientPaint} and {@code RadialGradientPaint}.
*/
public abstract class MultipleGradientPaint implements Paint {
The method to use when painting outside the gradient bounds.
/** The method to use when painting outside the gradient bounds.
*/
public static enum CycleMethod {
Use the terminal colors to fill the remaining area.
/**
* Use the terminal colors to fill the remaining area.
*/
NO_CYCLE,
Cycle the gradient colors start-to-end, end-to-start
to fill the remaining area.
/**
* Cycle the gradient colors start-to-end, end-to-start
* to fill the remaining area.
*/
REFLECT,
Cycle the gradient colors start-to-end, start-to-end
to fill the remaining area.
/**
* Cycle the gradient colors start-to-end, start-to-end
* to fill the remaining area.
*/
REPEAT
}
The color space in which to perform the gradient interpolation.
/** The color space in which to perform the gradient interpolation.
*/
public static enum ColorSpaceType {
Indicates that the color interpolation should occur in sRGB space.
/**
* Indicates that the color interpolation should occur in sRGB space.
*/
SRGB,
Indicates that the color interpolation should occur in linearized
RGB space.
/**
* Indicates that the color interpolation should occur in linearized
* RGB space.
*/
LINEAR_RGB
}
The transparency of this paint object. /** The transparency of this paint object. */
final int transparency;
Gradient keyframe values in the range 0 to 1. /** Gradient keyframe values in the range 0 to 1. */
final float[] fractions;
Gradient colors. /** Gradient colors. */
final Color[] colors;
Transform to apply to gradient. /** Transform to apply to gradient. */
final AffineTransform gradientTransform;
The method to use when painting outside the gradient bounds. /** The method to use when painting outside the gradient bounds. */
final CycleMethod cycleMethod;
The color space in which to perform the gradient interpolation. /** The color space in which to perform the gradient interpolation. */
final ColorSpaceType colorSpace;
The following fields are used only by MultipleGradientPaintContext
to cache certain values that remain constant and do not need to be
recalculated for each context created from this paint instance.
/**
* The following fields are used only by MultipleGradientPaintContext
* to cache certain values that remain constant and do not need to be
* recalculated for each context created from this paint instance.
*/
ColorModel model;
float[] normalizedIntervals;
boolean isSimpleLookup;
SoftReference<int[][]> gradients;
SoftReference<int[]> gradient;
int fastGradientArraySize;
Package-private constructor.
Params: - fractions – numbers ranging from 0.0 to 1.0 specifying the
distribution of colors along the gradient
- colors – array of colors corresponding to each fractional value
- cycleMethod – either
NO_CYCLE
, REFLECT
, or REPEAT
- colorSpace – which color space to use for interpolation, either
SRGB
or LINEAR_RGB
- gradientTransform – transform to apply to the gradient
Throws: - NullPointerException – if
fractions
array is null, or colors
array is null, or gradientTransform
is null, or cycleMethod
is null, or colorSpace
is null - IllegalArgumentException – if
fractions.length != colors.length
, or colors
is less than 2 in size, or a fractions
value is less than 0.0 or greater than 1.0, or the fractions
are not provided in strictly increasing order
/**
* Package-private constructor.
*
* @param fractions numbers ranging from 0.0 to 1.0 specifying the
* distribution of colors along the gradient
* @param colors array of colors corresponding to each fractional value
* @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
* or {@code REPEAT}
* @param colorSpace which color space to use for interpolation,
* either {@code SRGB} or {@code LINEAR_RGB}
* @param gradientTransform transform to apply to the gradient
*
* @throws NullPointerException
* if {@code fractions} array is null,
* or {@code colors} array is null,
* or {@code gradientTransform} is null,
* or {@code cycleMethod} is null,
* or {@code colorSpace} is null
* @throws IllegalArgumentException
* if {@code fractions.length != colors.length},
* or {@code colors} is less than 2 in size,
* or a {@code fractions} value is less than 0.0 or greater than 1.0,
* or the {@code fractions} are not provided in strictly increasing order
*/
MultipleGradientPaint(float[] fractions,
Color[] colors,
CycleMethod cycleMethod,
ColorSpaceType colorSpace,
AffineTransform gradientTransform)
{
if (fractions == null) {
throw new NullPointerException("Fractions array cannot be null");
}
if (colors == null) {
throw new NullPointerException("Colors array cannot be null");
}
if (cycleMethod == null) {
throw new NullPointerException("Cycle method cannot be null");
}
if (colorSpace == null) {
throw new NullPointerException("Color space cannot be null");
}
if (gradientTransform == null) {
throw new NullPointerException("Gradient transform cannot be "+
"null");
}
if (fractions.length != colors.length) {
throw new IllegalArgumentException("Colors and fractions must " +
"have equal size");
}
if (colors.length < 2) {
throw new IllegalArgumentException("User must specify at least " +
"2 colors");
}
// check that values are in the proper range and progress
// in increasing order from 0 to 1
float previousFraction = -1.0f;
for (float currentFraction : fractions) {
if (currentFraction < 0f || currentFraction > 1f) {
throw new IllegalArgumentException("Fraction values must " +
"be in the range 0 to 1: " +
currentFraction);
}
if (currentFraction <= previousFraction) {
throw new IllegalArgumentException("Keyframe fractions " +
"must be increasing: " +
currentFraction);
}
previousFraction = currentFraction;
}
// We have to deal with the cases where the first gradient stop is not
// equal to 0 and/or the last gradient stop is not equal to 1.
// In both cases, create a new point and replicate the previous
// extreme point's color.
boolean fixFirst = false;
boolean fixLast = false;
int len = fractions.length;
int off = 0;
if (fractions[0] != 0f) {
// first stop is not equal to zero, fix this condition
fixFirst = true;
len++;
off++;
}
if (fractions[fractions.length-1] != 1f) {
// last stop is not equal to one, fix this condition
fixLast = true;
len++;
}
this.fractions = new float[len];
System.arraycopy(fractions, 0, this.fractions, off, fractions.length);
this.colors = new Color[len];
System.arraycopy(colors, 0, this.colors, off, colors.length);
if (fixFirst) {
this.fractions[0] = 0f;
this.colors[0] = colors[0];
}
if (fixLast) {
this.fractions[len-1] = 1f;
this.colors[len-1] = colors[colors.length - 1];
}
// copy some flags
this.colorSpace = colorSpace;
this.cycleMethod = cycleMethod;
// copy the gradient transform
this.gradientTransform = new AffineTransform(gradientTransform);
// determine transparency
boolean opaque = true;
for (int i = 0; i < colors.length; i++){
opaque = opaque && (colors[i].getAlpha() == 0xff);
}
this.transparency = opaque ? OPAQUE : TRANSLUCENT;
}
Returns a copy of the array of floats used by this gradient
to calculate color distribution.
The returned array always has 0 as its first value and 1 as its
last value, with increasing values in between.
Returns: a copy of the array of floats used by this gradient to
calculate color distribution
/**
* Returns a copy of the array of floats used by this gradient
* to calculate color distribution.
* The returned array always has 0 as its first value and 1 as its
* last value, with increasing values in between.
*
* @return a copy of the array of floats used by this gradient to
* calculate color distribution
*/
public final float[] getFractions() {
float[] copy = new float[fractions.length];
System.arraycopy(fractions, 0, copy, 0, fractions.length);
return copy;
}
Returns a copy of the array of colors used by this gradient.
The first color maps to the first value in the fractions array,
and the last color maps to the last value in the fractions array.
Returns: a copy of the array of colors used by this gradient
/**
* Returns a copy of the array of colors used by this gradient.
* The first color maps to the first value in the fractions array,
* and the last color maps to the last value in the fractions array.
*
* @return a copy of the array of colors used by this gradient
*/
public final Color[] getColors() {
Color[] copy = new Color[fractions.length];
System.arraycopy(fractions, 0, copy, 0, fractions.length);
return copy;
}
Returns the enumerated type which specifies cycling behavior.
Returns: the enumerated type which specifies cycling behavior
/**
* Returns the enumerated type which specifies cycling behavior.
*
* @return the enumerated type which specifies cycling behavior
*/
public final CycleMethod getCycleMethod() {
return cycleMethod;
}
Returns the enumerated type which specifies color space for
interpolation.
Returns: the enumerated type which specifies color space for
interpolation
/**
* Returns the enumerated type which specifies color space for
* interpolation.
*
* @return the enumerated type which specifies color space for
* interpolation
*/
public final ColorSpaceType getColorSpace() {
return colorSpace;
}
Returns a copy of the transform applied to the gradient.
Returns: a copy of the transform applied to the gradient
/**
* Returns a copy of the transform applied to the gradient.
*
* @return a copy of the transform applied to the gradient
*/
public final AffineTransform getTransform() {
return new AffineTransform(gradientTransform);
}
Returns the transparency mode for this Paint object.
See Also: Returns: an integer value representing the transparency mode for
this Paint object
/**
* Returns the transparency mode for this Paint object.
*
* @return an integer value representing the transparency mode for
* this Paint object
* @see java.awt.Transparency
*/
public final int getTransparency() {
return transparency;
}
}