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 009package com.kitfox.svg.batik; 010 011import java.awt.Color; 012import java.awt.Paint; 013import 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 026public 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}