jdk/src/share/classes/java/awt/MultipleGradientPaint.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/MultipleGradientPaint.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,305 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.image.ColorModel;
+import java.lang.ref.SoftReference;
+import java.util.Arrays;
+
+/**
+ * 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}.
+ *
+ * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
+ * @since 1.6
+ */
+public abstract class MultipleGradientPaint implements Paint {
+
+    /** The method to use when painting outside the gradient bounds.
+     * @since 1.6
+     */
+    public static enum CycleMethod {
+        /**
+         * 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.
+         */
+        REFLECT,
+
+        /**
+         * 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.
+     * @since 1.6
+     */
+    public static enum ColorSpaceType {
+        /**
+         * Indicates that the color interpolation should occur in sRGB space.
+         */
+        SRGB,
+
+        /**
+         * Indicates that the color interpolation should occur in linearized
+         * RGB space.
+         */
+        LINEAR_RGB
+    }
+
+    /** The transparency of this paint object. */
+    final int transparency;
+
+    /** Gradient keyframe values in the range 0 to 1. */
+    final float[] fractions;
+
+    /** Gradient colors. */
+    final Color[] colors;
+
+    /** Transform to apply to gradient. */
+    final AffineTransform gradientTransform;
+
+    /** The method to use when painting outside the gradient bounds. */
+    final CycleMethod cycleMethod;
+
+    /** 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.
+     */
+    ColorModel model;
+    float[] normalizedIntervals;
+    boolean isSimpleLookup;
+    SoftReference<int[][]> gradients;
+    SoftReference<int[]> gradient;
+    int fastGradientArraySize;
+
+    /**
+     * 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.
+     *
+     * @return a copy of the array of floats used by this gradient to
+     * calculate color distribution
+     */
+    public final float[] getFractions() {
+        return Arrays.copyOf(fractions, fractions.length);
+    }
+
+    /**
+     * 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() {
+        return Arrays.copyOf(colors, colors.length);
+    }
+
+    /**
+     * 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.
+     *
+     * @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.
+     *
+     * @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.
+     *
+     * @return an integer value representing the transparency mode for
+     * this Paint object
+     * @see java.awt.Transparency
+     */
+    public final int getTransparency() {
+        return transparency;
+    }
+}