jdk/src/share/classes/java/awt/MultipleGradientPaint.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package java.awt;
       
    27 
       
    28 import java.awt.geom.AffineTransform;
       
    29 import java.awt.image.ColorModel;
       
    30 import java.lang.ref.SoftReference;
       
    31 import java.util.Arrays;
       
    32 
       
    33 /**
       
    34  * This is the superclass for Paints which use a multiple color
       
    35  * gradient to fill in their raster.  It provides storage for variables and
       
    36  * enumerated values common to
       
    37  * {@code LinearGradientPaint} and {@code RadialGradientPaint}.
       
    38  *
       
    39  * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
       
    40  * @since 1.6
       
    41  */
       
    42 public abstract class MultipleGradientPaint implements Paint {
       
    43 
       
    44     /** The method to use when painting outside the gradient bounds.
       
    45      * @since 1.6
       
    46      */
       
    47     public static enum CycleMethod {
       
    48         /**
       
    49          * Use the terminal colors to fill the remaining area.
       
    50          */
       
    51         NO_CYCLE,
       
    52 
       
    53         /**
       
    54          * Cycle the gradient colors start-to-end, end-to-start
       
    55          * to fill the remaining area.
       
    56          */
       
    57         REFLECT,
       
    58 
       
    59         /**
       
    60          * Cycle the gradient colors start-to-end, start-to-end
       
    61          * to fill the remaining area.
       
    62          */
       
    63         REPEAT
       
    64     }
       
    65 
       
    66     /** The color space in which to perform the gradient interpolation.
       
    67      * @since 1.6
       
    68      */
       
    69     public static enum ColorSpaceType {
       
    70         /**
       
    71          * Indicates that the color interpolation should occur in sRGB space.
       
    72          */
       
    73         SRGB,
       
    74 
       
    75         /**
       
    76          * Indicates that the color interpolation should occur in linearized
       
    77          * RGB space.
       
    78          */
       
    79         LINEAR_RGB
       
    80     }
       
    81 
       
    82     /** The transparency of this paint object. */
       
    83     final int transparency;
       
    84 
       
    85     /** Gradient keyframe values in the range 0 to 1. */
       
    86     final float[] fractions;
       
    87 
       
    88     /** Gradient colors. */
       
    89     final Color[] colors;
       
    90 
       
    91     /** Transform to apply to gradient. */
       
    92     final AffineTransform gradientTransform;
       
    93 
       
    94     /** The method to use when painting outside the gradient bounds. */
       
    95     final CycleMethod cycleMethod;
       
    96 
       
    97     /** The color space in which to perform the gradient interpolation. */
       
    98     final ColorSpaceType colorSpace;
       
    99 
       
   100     /**
       
   101      * The following fields are used only by MultipleGradientPaintContext
       
   102      * to cache certain values that remain constant and do not need to be
       
   103      * recalculated for each context created from this paint instance.
       
   104      */
       
   105     ColorModel model;
       
   106     float[] normalizedIntervals;
       
   107     boolean isSimpleLookup;
       
   108     SoftReference<int[][]> gradients;
       
   109     SoftReference<int[]> gradient;
       
   110     int fastGradientArraySize;
       
   111 
       
   112     /**
       
   113      * Package-private constructor.
       
   114      *
       
   115      * @param fractions numbers ranging from 0.0 to 1.0 specifying the
       
   116      *                  distribution of colors along the gradient
       
   117      * @param colors array of colors corresponding to each fractional value
       
   118      * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
       
   119      *                    or {@code REPEAT}
       
   120      * @param colorSpace which color space to use for interpolation,
       
   121      *                   either {@code SRGB} or {@code LINEAR_RGB}
       
   122      * @param gradientTransform transform to apply to the gradient
       
   123      *
       
   124      * @throws NullPointerException
       
   125      * if {@code fractions} array is null,
       
   126      * or {@code colors} array is null,
       
   127      * or {@code gradientTransform} is null,
       
   128      * or {@code cycleMethod} is null,
       
   129      * or {@code colorSpace} is null
       
   130      * @throws IllegalArgumentException
       
   131      * if {@code fractions.length != colors.length},
       
   132      * or {@code colors} is less than 2 in size,
       
   133      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
       
   134      * or the {@code fractions} are not provided in strictly increasing order
       
   135      */
       
   136     MultipleGradientPaint(float[] fractions,
       
   137                           Color[] colors,
       
   138                           CycleMethod cycleMethod,
       
   139                           ColorSpaceType colorSpace,
       
   140                           AffineTransform gradientTransform)
       
   141     {
       
   142         if (fractions == null) {
       
   143             throw new NullPointerException("Fractions array cannot be null");
       
   144         }
       
   145 
       
   146         if (colors == null) {
       
   147             throw new NullPointerException("Colors array cannot be null");
       
   148         }
       
   149 
       
   150         if (cycleMethod == null) {
       
   151             throw new NullPointerException("Cycle method cannot be null");
       
   152         }
       
   153 
       
   154         if (colorSpace == null) {
       
   155             throw new NullPointerException("Color space cannot be null");
       
   156         }
       
   157 
       
   158         if (gradientTransform == null) {
       
   159             throw new NullPointerException("Gradient transform cannot be "+
       
   160                                            "null");
       
   161         }
       
   162 
       
   163         if (fractions.length != colors.length) {
       
   164             throw new IllegalArgumentException("Colors and fractions must " +
       
   165                                                "have equal size");
       
   166         }
       
   167 
       
   168         if (colors.length < 2) {
       
   169             throw new IllegalArgumentException("User must specify at least " +
       
   170                                                "2 colors");
       
   171         }
       
   172 
       
   173         // check that values are in the proper range and progress
       
   174         // in increasing order from 0 to 1
       
   175         float previousFraction = -1.0f;
       
   176         for (float currentFraction : fractions) {
       
   177             if (currentFraction < 0f || currentFraction > 1f) {
       
   178                 throw new IllegalArgumentException("Fraction values must " +
       
   179                                                    "be in the range 0 to 1: " +
       
   180                                                    currentFraction);
       
   181             }
       
   182 
       
   183             if (currentFraction <= previousFraction) {
       
   184                 throw new IllegalArgumentException("Keyframe fractions " +
       
   185                                                    "must be increasing: " +
       
   186                                                    currentFraction);
       
   187             }
       
   188 
       
   189             previousFraction = currentFraction;
       
   190         }
       
   191 
       
   192         // We have to deal with the cases where the first gradient stop is not
       
   193         // equal to 0 and/or the last gradient stop is not equal to 1.
       
   194         // In both cases, create a new point and replicate the previous
       
   195         // extreme point's color.
       
   196         boolean fixFirst = false;
       
   197         boolean fixLast = false;
       
   198         int len = fractions.length;
       
   199         int off = 0;
       
   200 
       
   201         if (fractions[0] != 0f) {
       
   202             // first stop is not equal to zero, fix this condition
       
   203             fixFirst = true;
       
   204             len++;
       
   205             off++;
       
   206         }
       
   207         if (fractions[fractions.length-1] != 1f) {
       
   208             // last stop is not equal to one, fix this condition
       
   209             fixLast = true;
       
   210             len++;
       
   211         }
       
   212 
       
   213         this.fractions = new float[len];
       
   214         System.arraycopy(fractions, 0, this.fractions, off, fractions.length);
       
   215         this.colors = new Color[len];
       
   216         System.arraycopy(colors, 0, this.colors, off, colors.length);
       
   217 
       
   218         if (fixFirst) {
       
   219             this.fractions[0] = 0f;
       
   220             this.colors[0] = colors[0];
       
   221         }
       
   222         if (fixLast) {
       
   223             this.fractions[len-1] = 1f;
       
   224             this.colors[len-1] = colors[colors.length - 1];
       
   225         }
       
   226 
       
   227         // copy some flags
       
   228         this.colorSpace = colorSpace;
       
   229         this.cycleMethod = cycleMethod;
       
   230 
       
   231         // copy the gradient transform
       
   232         this.gradientTransform = new AffineTransform(gradientTransform);
       
   233 
       
   234         // determine transparency
       
   235         boolean opaque = true;
       
   236         for (int i = 0; i < colors.length; i++){
       
   237             opaque = opaque && (colors[i].getAlpha() == 0xff);
       
   238         }
       
   239         this.transparency = opaque ? OPAQUE : TRANSLUCENT;
       
   240     }
       
   241 
       
   242     /**
       
   243      * Returns a copy of the array of floats used by this gradient
       
   244      * to calculate color distribution.
       
   245      * The returned array always has 0 as its first value and 1 as its
       
   246      * last value, with increasing values in between.
       
   247      *
       
   248      * @return a copy of the array of floats used by this gradient to
       
   249      * calculate color distribution
       
   250      */
       
   251     public final float[] getFractions() {
       
   252         return Arrays.copyOf(fractions, fractions.length);
       
   253     }
       
   254 
       
   255     /**
       
   256      * Returns a copy of the array of colors used by this gradient.
       
   257      * The first color maps to the first value in the fractions array,
       
   258      * and the last color maps to the last value in the fractions array.
       
   259      *
       
   260      * @return a copy of the array of colors used by this gradient
       
   261      */
       
   262     public final Color[] getColors() {
       
   263         return Arrays.copyOf(colors, colors.length);
       
   264     }
       
   265 
       
   266     /**
       
   267      * Returns the enumerated type which specifies cycling behavior.
       
   268      *
       
   269      * @return the enumerated type which specifies cycling behavior
       
   270      */
       
   271     public final CycleMethod getCycleMethod() {
       
   272         return cycleMethod;
       
   273     }
       
   274 
       
   275     /**
       
   276      * Returns the enumerated type which specifies color space for
       
   277      * interpolation.
       
   278      *
       
   279      * @return the enumerated type which specifies color space for
       
   280      * interpolation
       
   281      */
       
   282     public final ColorSpaceType getColorSpace() {
       
   283         return colorSpace;
       
   284     }
       
   285 
       
   286     /**
       
   287      * Returns a copy of the transform applied to the gradient.
       
   288      *
       
   289      * @return a copy of the transform applied to the gradient
       
   290      */
       
   291     public final AffineTransform getTransform() {
       
   292         return new AffineTransform(gradientTransform);
       
   293     }
       
   294 
       
   295     /**
       
   296      * Returns the transparency mode for this Paint object.
       
   297      *
       
   298      * @return an integer value representing the transparency mode for
       
   299      * this Paint object
       
   300      * @see java.awt.Transparency
       
   301      */
       
   302     public final int getTransparency() {
       
   303         return transparency;
       
   304     }
       
   305 }