001    /*****************************************************************************
002     * Copyright (C) The Apache Software Foundation. All rights reserved.        *
003     * ------------------------------------------------------------------------- *
004     * This software is published under the terms of the Apache Software License *
005     * version 1.1, a copy of which has been included with this distribution in  *
006     * the LICENSE file.                                                         *
007     *****************************************************************************/
008    
009    package com.kitfox.svg.batik;
010    
011    import java.awt.Color;
012    import java.awt.Paint;
013    import java.awt.geom.AffineTransform;
014    
015    /** This is the superclass for Paints which use a multiple color
016     * gradient to fill in their raster.  It provides storage for variables and
017     * enumerated values common to LinearGradientPaint and RadialGradientPaint.
018     *
019     *
020     * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
021     * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
022     * @version $Id: MultipleGradientPaint.java,v 1.2 2004/09/27 09:27:27 kitfox Exp $
023     *
024     */
025    
026    public abstract class MultipleGradientPaint implements Paint {
027    
028        /** Transparency. */
029        protected int transparency;
030    
031        /** Gradient keyframe values in the range 0 to 1. */
032        protected float[] fractions;
033    
034        /** Gradient colors. */
035        protected Color[] colors;
036    
037        /** Transform to apply to gradient. */
038        protected AffineTransform gradientTransform;
039    
040        /** The method to use when painting out of the gradient bounds. */
041        protected CycleMethodEnum cycleMethod;
042    
043        /** The colorSpace in which to perform the interpolation. */
044        protected ColorSpaceEnum colorSpace;
045    
046        /** Inner class to allow for typesafe enumerated ColorSpace values. */
047        public static class ColorSpaceEnum {
048        }
049    
050        /** Inner class to allow for typesafe enumerated CycleMethod values. */
051        public static class CycleMethodEnum {
052        }
053    
054        /** Indicates (if the gradient starts or ends inside the target region)
055         *  to use the terminal colors to fill the remaining area. (default)
056         */
057        public static final CycleMethodEnum NO_CYCLE = new CycleMethodEnum();
058    
059        /** Indicates (if the gradient starts or ends inside the target region),
060         *  to cycle the gradient colors start-to-end, end-to-start to fill the
061         *  remaining area.
062         */
063        public static final CycleMethodEnum REFLECT = new CycleMethodEnum();
064    
065        /** Indicates (if the gradient starts or ends inside the target region),
066         *  to cycle the gradient colors start-to-end, start-to-end to fill the
067         *  remaining area.
068         */
069        public static final CycleMethodEnum REPEAT = new CycleMethodEnum();
070    
071        /** Indicates that the color interpolation should occur in sRGB space.
072         *  (default)
073         */
074        public static final ColorSpaceEnum SRGB = new ColorSpaceEnum();
075    
076        /** Indicates that the color interpolation should occur in linearized
077         *  RGB space.
078         */
079        public static final ColorSpaceEnum LINEAR_RGB = new ColorSpaceEnum();
080    
081    
082         /**
083         * Superclass constructor, typical user should never have to call this.
084         *
085         * @param fractions numbers ranging from 0.0 to 1.0 specifying the
086         * distribution of colors along the gradient
087         *
088         * @param colors array of colors corresponding to each fractional value
089         *
090         * @param cycleMethod either NO_CYCLE, REFLECT, or REPEAT
091         *
092         * @param colorSpace which colorspace to use for interpolation,
093         * either SRGB or LINEAR_RGB
094         *
095         * @param gradientTransform transform to apply to the gradient
096         *
097         * @throws NullPointerException if arrays are null, or
098         * gradientTransform is null
099         *
100         * @throws IllegalArgumentException if fractions.length != colors.length,
101         * or if colors is less than 2 in size, or if an enumerated value is bad.
102         *
103         * @see java.awt.PaintContext
104         */
105        public MultipleGradientPaint(float[] fractions,
106                                     Color[] colors,
107                                     CycleMethodEnum cycleMethod,
108                                     ColorSpaceEnum colorSpace,
109                                     AffineTransform gradientTransform) {
110    
111            if (fractions == null) {
112                throw new IllegalArgumentException("Fractions array cannot be " +
113                                                   "null");
114            }
115    
116            if (colors == null) {
117                throw new IllegalArgumentException("Colors array cannot be null");
118            }
119    
120            if (fractions.length != colors.length) {
121                throw new IllegalArgumentException("Colors and fractions must " +
122                                                   "have equal size");
123            }
124    
125            if (colors.length < 2) {
126                throw new IllegalArgumentException("User must specify at least " +
127                                                   "2 colors");
128            }
129    
130            if ((colorSpace != LINEAR_RGB) &&
131                (colorSpace != SRGB)) {
132                throw new IllegalArgumentException("Invalid colorspace for " +
133                                                   "interpolation.");
134            }
135    
136            if ((cycleMethod != NO_CYCLE) &&
137                (cycleMethod != REFLECT) &&
138                (cycleMethod != REPEAT)) {
139                throw new IllegalArgumentException("Invalid cycle method.");
140            }
141    
142            if (gradientTransform == null) {
143                throw new IllegalArgumentException("Gradient transform cannot be "+
144                                                   "null.");
145            }
146    
147            //copy the fractions array
148            this.fractions = new float[fractions.length];
149            System.arraycopy(fractions, 0, this.fractions, 0, fractions.length);
150    
151            //copy the colors array
152            this.colors = new Color[colors.length];
153            System.arraycopy(colors, 0, this.colors, 0, colors.length);
154    
155            //copy some flags
156            this.colorSpace = colorSpace;
157            this.cycleMethod = cycleMethod;
158    
159            //copy the gradient transform
160            this.gradientTransform = (AffineTransform)gradientTransform.clone();
161    
162            // Process transparency
163            boolean opaque = true;
164            for(int i=0; i<colors.length; i++){
165                opaque = opaque && (colors[i].getAlpha()==0xff);
166            }
167    
168            if(opaque) {
169                transparency = OPAQUE;
170            }
171    
172            else {
173                transparency = TRANSLUCENT;
174            }
175        }
176    
177        /**
178         * Returns a copy of the array of colors used by this gradient.
179         * @return a copy of the array of colors used by this gradient
180         *
181         */
182        public Color[] getColors() {
183            Color colors[] = new Color[this.colors.length];
184            System.arraycopy(this.colors, 0, colors, 0, this.colors.length);
185            return colors;
186        }
187    
188        /**
189         * Returns a copy of the array of floats used by this gradient
190         * to calculate color distribution.
191         * @return a copy of the array of floats used by this gradient to
192         * calculate color distribution
193         *
194         */
195        public float[] getFractions() {
196            float fractions[] = new float[this.fractions.length];
197            System.arraycopy(this.fractions, 0, fractions, 0, this.fractions.length);
198            return fractions;
199        }
200    
201        /**
202         * Returns the transparency mode for this LinearGradientPaint.
203         * @return an integer value representing this LinearGradientPaint object's
204         * transparency mode.
205         * @see java.awt.Transparency
206         */
207        public int getTransparency() {
208            return transparency;
209        }
210    
211        /**
212         * Returns the enumerated type which specifies cycling behavior.
213         * @return the enumerated type which specifies cycling behavior
214         */
215        public CycleMethodEnum getCycleMethod() {
216            return cycleMethod;
217        }
218    
219        /**
220         * Returns the enumerated type which specifies color space for
221         * interpolation.
222         * @return the enumerated type which specifies color space for
223         * interpolation
224         */
225        public ColorSpaceEnum getColorSpace() {
226            return colorSpace;
227        }
228    
229        /**
230         * Returns a copy of the transform applied to the gradient.
231         * @return a copy of the transform applied to the gradient.
232         */
233        public AffineTransform getTransform() {
234            return (AffineTransform)gradientTransform.clone();
235        }
236    }