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:56 AM
035 */
036package com.kitfox.svg;
037
038import com.kitfox.svg.xml.StyleAttribute;
039import java.awt.Shape;
040import java.awt.geom.Area;
041
042/**
043 * @author Mark McKay
044 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
045 */
046public class ClipPath extends SVGElement
047{
048
049    public static final String TAG_NAME = "clippath";
050    public static final int CP_USER_SPACE_ON_USE = 0;
051    public static final int CP_OBJECT_BOUNDING_BOX = 1;
052    int clipPathUnits = CP_USER_SPACE_ON_USE;
053
054    /**
055     * Creates a new instance of Stop
056     */
057    public ClipPath()
058    {
059    }
060
061    @Override
062    public String getTagName()
063    {
064        return TAG_NAME;
065    }
066
067    /**
068     * Called after the start element but before the end element to indicate
069     * each child tag that has been processed
070     */
071    @Override
072    public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
073    {
074        super.loaderAddChild(helper, child);
075    }
076
077    @Override
078    protected void build() throws SVGException
079    {
080        super.build();
081
082        StyleAttribute sty = new StyleAttribute();
083
084        clipPathUnits = (getPres(sty.setName("clipPathUnits"))
085            && sty.getStringValue().equals("objectBoundingBox"))
086            ? CP_OBJECT_BOUNDING_BOX
087            : CP_USER_SPACE_ON_USE;
088    }
089
090    public int getClipPathUnits()
091    {
092        return clipPathUnits;
093    }
094
095    public Shape getClipPathShape()
096    {
097        if (children.isEmpty())
098        {
099            return null;
100        }
101        if (children.size() == 1)
102        {
103            return ((ShapeElement) children.get(0)).getShape();
104        }
105
106        Area clipArea = null;
107        for (SVGElement svgElement : children) {
108            ShapeElement se = (ShapeElement) svgElement;
109
110            if (clipArea == null)
111            {
112                Shape shape = se.getShape();
113                if (shape != null)
114                {
115                    clipArea = new Area(se.getShape());
116                }
117                continue;
118            }
119
120            Shape shape = se.getShape();
121            if (shape != null)
122            {
123                clipArea.intersect(new Area(shape));
124            }
125        }
126
127        return clipArea;
128    }
129
130    /**
131     * Updates all attributes in this diagram associated with a time event. Ie,
132     * all attributes with track information.
133     *
134     * @param curTime Time at which to evaluate node
135     * @return - true if this node has changed state as a result of the time
136     * update
137     * @throws com.kitfox.svg.SVGException
138     */
139    @Override
140    public boolean updateTime(double curTime) throws SVGException
141    {
142        //Get current values for parameters
143        StyleAttribute sty = new StyleAttribute();
144        boolean shapeChange = false;
145
146
147        if (getPres(sty.setName("clipPathUnits")))
148        {
149            String newUnitsStrn = sty.getStringValue();
150            int newUnits = newUnitsStrn.equals("objectBoundingBox")
151                ? CP_OBJECT_BOUNDING_BOX
152                : CP_USER_SPACE_ON_USE;
153
154            if (newUnits != clipPathUnits)
155            {
156                clipPathUnits = newUnits;
157                shapeChange = true;
158            }
159        }
160
161        if (shapeChange)
162        {
163            build();
164        }
165
166        for (int i = 0; i < children.size(); ++i)
167        {
168            SVGElement ele = (SVGElement) children.get(i);
169            ele.updateTime(curTime);
170        }
171        
172        return shapeChange;
173    }
174}