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;
041import java.util.Iterator;
042
043/**
044 * @author Mark McKay
045 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
046 */
047public class ClipPath extends SVGElement
048{
049
050    public static final String TAG_NAME = "clippath";
051    public static final int CP_USER_SPACE_ON_USE = 0;
052    public static final int CP_OBJECT_BOUNDING_BOX = 1;
053    int clipPathUnits = CP_USER_SPACE_ON_USE;
054
055    /**
056     * Creates a new instance of Stop
057     */
058    public ClipPath()
059    {
060    }
061
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    public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
072    {
073        super.loaderAddChild(helper, child);
074    }
075
076    protected void build() throws SVGException
077    {
078        super.build();
079
080        StyleAttribute sty = new StyleAttribute();
081
082        clipPathUnits = (getPres(sty.setName("clipPathUnits"))
083            && sty.getStringValue().equals("objectBoundingBox"))
084            ? CP_OBJECT_BOUNDING_BOX
085            : CP_USER_SPACE_ON_USE;
086    }
087
088    public int getClipPathUnits()
089    {
090        return clipPathUnits;
091    }
092
093    public Shape getClipPathShape()
094    {
095        if (children.isEmpty())
096        {
097            return null;
098        }
099        if (children.size() == 1)
100        {
101            return ((ShapeElement) children.get(0)).getShape();
102        }
103
104        Area clipArea = null;
105        for (Iterator it = children.iterator(); it.hasNext();)
106        {
107            ShapeElement se = (ShapeElement) it.next();
108
109            if (clipArea == null)
110            {
111                Shape shape = se.getShape();
112                if (shape != null)
113                {
114                    clipArea = new Area(se.getShape());
115                }
116                continue;
117            }
118
119            Shape shape = se.getShape();
120            if (shape != null)
121            {
122                clipArea.intersect(new Area(shape));
123            }
124        }
125
126        return clipArea;
127    }
128
129    /**
130     * Updates all attributes in this diagram associated with a time event. Ie,
131     * all attributes with track information.
132     *
133     * @return - true if this node has changed state as a result of the time
134     * update
135     */
136    public boolean updateTime(double curTime) throws SVGException
137    {
138        //Get current values for parameters
139        StyleAttribute sty = new StyleAttribute();
140        boolean shapeChange = false;
141
142
143        if (getPres(sty.setName("clipPathUnits")))
144        {
145            String newUnitsStrn = sty.getStringValue();
146            int newUnits = newUnitsStrn.equals("objectBoundingBox")
147                ? CP_OBJECT_BOUNDING_BOX
148                : CP_USER_SPACE_ON_USE;
149
150            if (newUnits != clipPathUnits)
151            {
152                clipPathUnits = newUnits;
153                shapeChange = true;
154            }
155        }
156
157        if (shapeChange)
158        {
159            build();
160        }
161
162        return shapeChange;
163    }
164}