001/*
002 * SVG Salamander
003 * Copyright (c) 2004, Mark McKay
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or 
007 * without modification, are permitted provided that the following
008 * conditions are met:
009 *
010 *   - Redistributions of source code must retain the above 
011 *     copyright notice, this list of conditions and the following
012 *     disclaimer.
013 *   - Redistributions in binary form must reproduce the above
014 *     copyright notice, this list of conditions and the following
015 *     disclaimer in the documentation and/or other materials 
016 *     provided with the distribution.
017 *
018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
019 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
020 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
021 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
022 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
023 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
025 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
026 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
027 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
029 * OF THE POSSIBILITY OF SUCH DAMAGE. 
030 * 
031 * Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
032 * projects can be found at http://www.kitfox.com
033 *
034 * Created on January 26, 2004, 1:55 AM
035 */
036package com.kitfox.svg;
037
038import com.kitfox.svg.xml.StyleAttribute;
039import java.awt.Color;
040import java.awt.MultipleGradientPaint;
041import java.awt.Paint;
042import java.awt.RadialGradientPaint;
043import java.awt.geom.AffineTransform;
044import java.awt.geom.Point2D;
045import java.awt.geom.Rectangle2D;
046
047/**
048 * @author Mark McKay
049 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
050 */
051public class RadialGradient extends Gradient
052{
053    public static final String TAG_NAME = "radialgradient";
054
055    float cx = 0.5f;
056    float cy = 0.5f;
057    boolean hasFocus = false;
058    float fx = 0f;
059    float fy = 0f;
060    float r = 0.5f;
061
062    /**
063     * Creates a new instance of RadialGradient
064     */
065    public RadialGradient()
066    {
067    }
068
069    @Override
070    public String getTagName()
071    {
072        return TAG_NAME;
073    }
074
075    @Override
076    protected void build() throws SVGException
077    {
078        super.build();
079
080        StyleAttribute sty = new StyleAttribute();
081
082        if (getPres(sty.setName("cx")))
083        {
084            cx = sty.getFloatValueWithUnits();
085        }
086
087        if (getPres(sty.setName("cy")))
088        {
089            cy = sty.getFloatValueWithUnits();
090        }
091
092        hasFocus = false;
093        if (getPres(sty.setName("fx")))
094        {
095            fx = sty.getFloatValueWithUnits();
096            hasFocus = true;
097        }
098
099        if (getPres(sty.setName("fy")))
100        {
101            fy = sty.getFloatValueWithUnits();
102            hasFocus = true;
103        }
104
105        if (getPres(sty.setName("r")))
106        {
107            r = sty.getFloatValueWithUnits();
108        }
109    }
110
111    @Override
112    public Paint getPaint(Rectangle2D bounds, AffineTransform xform)
113    {
114        MultipleGradientPaint.CycleMethod method;
115        switch (spreadMethod)
116        {
117            default:
118            case SM_PAD:
119                method = MultipleGradientPaint.CycleMethod.NO_CYCLE;
120                break;
121            case SM_REPEAT:
122                method = MultipleGradientPaint.CycleMethod.REPEAT;
123                break;
124            case SM_REFLECT:
125                method = MultipleGradientPaint.CycleMethod.REFLECT;
126                break;
127        }
128
129        Paint paint;
130        Point2D.Float pt1 = new Point2D.Float(cx, cy);
131        Point2D.Float pt2 = hasFocus ? new Point2D.Float(fx, fy) : pt1;
132        float[] stopFractions = getStopFractions();
133        Color[] stopColors = getStopColors();
134        
135        //Verify that the stop fractions are valid
136        {
137            //for (int i = 0; i < 
138        }
139        
140        if (gradientUnits == GU_USER_SPACE_ON_USE)
141        {
142            paint = new RadialGradientPaint(
143                pt1,
144                r,
145                pt2,
146                stopFractions,
147                stopColors,
148                method,
149                MultipleGradientPaint.ColorSpaceType.SRGB,
150                gradientTransform);
151        } else
152        {
153            AffineTransform viewXform = new AffineTransform();
154            viewXform.translate(bounds.getX(), bounds.getY());
155            viewXform.scale(bounds.getWidth(), bounds.getHeight());
156
157            viewXform.concatenate(gradientTransform);
158
159            paint = new RadialGradientPaint(
160                pt1,
161                r,
162                pt2,
163                stopFractions,
164                stopColors,
165                method,
166                MultipleGradientPaint.ColorSpaceType.SRGB,
167                viewXform);
168        }
169
170        return paint;
171    }
172
173    /**
174     * Updates all attributes in this diagram associated with a time event. Ie,
175     * all attributes with track information.
176     *
177     * @return - true if this node has changed state as a result of the time
178     * update
179     */
180    @Override
181    public boolean updateTime(double curTime) throws SVGException
182    {
183//        if (trackManager.getNumTracks() == 0) return false;
184        boolean changeState = super.updateTime(curTime);
185
186        //Get current values for parameters
187        StyleAttribute sty = new StyleAttribute();
188        boolean shapeChange = false;
189
190        if (getPres(sty.setName("cx")))
191        {
192            float newVal = sty.getFloatValueWithUnits();
193            if (newVal != cx)
194            {
195                cx = newVal;
196                shapeChange = true;
197            }
198        }
199
200        if (getPres(sty.setName("cy")))
201        {
202            float newVal = sty.getFloatValueWithUnits();
203            if (newVal != cy)
204            {
205                cy = newVal;
206                shapeChange = true;
207            }
208        }
209
210        if (getPres(sty.setName("fx")))
211        {
212            float newVal = sty.getFloatValueWithUnits();
213            if (newVal != fx)
214            {
215                fx = newVal;
216                shapeChange = true;
217            }
218        }
219
220        if (getPres(sty.setName("fy")))
221        {
222            float newVal = sty.getFloatValueWithUnits();
223            if (newVal != fy)
224            {
225                fy = newVal;
226                shapeChange = true;
227            }
228        }
229
230        if (getPres(sty.setName("r")))
231        {
232            float newVal = sty.getFloatValueWithUnits();
233            if (newVal != r)
234            {
235                r = newVal;
236                shapeChange = true;
237            }
238        }
239
240        return changeState;
241    }
242}