summaryrefslogtreecommitdiffstats
path: root/src/main/java/com/kitfox/svg/animation/AnimationElement.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/kitfox/svg/animation/AnimationElement.java')
-rw-r--r--src/main/java/com/kitfox/svg/animation/AnimationElement.java336
1 files changed, 336 insertions, 0 deletions
diff --git a/src/main/java/com/kitfox/svg/animation/AnimationElement.java b/src/main/java/com/kitfox/svg/animation/AnimationElement.java
new file mode 100644
index 0000000..e1c7cd9
--- /dev/null
+++ b/src/main/java/com/kitfox/svg/animation/AnimationElement.java
@@ -0,0 +1,336 @@
+/*
+ * AnimateEle.java
+ *
+ * The Salamander Project - 2D and 3D graphics libraries in Java
+ * Copyright (C) 2004 Mark McKay
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Mark McKay can be contacted at mark@kitfox.com. Salamander and other
+ * projects can be found at http://www.kitfox.com
+ *
+ * Created on August 15, 2004, 2:52 AM
+ */
+
+package com.kitfox.svg.animation;
+
+import java.io.*;
+import org.xml.sax.*;
+
+import com.kitfox.svg.*;
+
+/**
+ * @author Mark McKay
+ * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
+ */
+public abstract class AnimationElement extends SVGElement
+{
+ protected String attribName;
+// protected String attribType;
+ protected int attribType = AT_AUTO;
+
+ public static final int AT_CSS = 0;
+ public static final int AT_XML = 1;
+ public static final int AT_AUTO = 2; //Check CSS first, then XML
+
+ protected TimeBase beginTime;
+ protected TimeBase durTime;
+ protected TimeBase endTime;
+ protected int fillType = FT_AUTO;
+
+ /** <a href="http://www.w3.org/TR/smil20/smil-timing.html#adef-fill">More about the <b>fill</b> attribute</a> */
+ public static final int FT_REMOVE = 0;
+ public static final int FT_FREEZE = 1;
+ public static final int FT_HOLD = 2;
+ public static final int FT_TRANSITION = 3;
+ public static final int FT_AUTO = 4;
+ public static final int FT_DEFAULT = 5;
+
+ /** Additive state of track */
+ public static final int AD_REPLACE = 0;
+ public static final int AD_SUM = 1;
+
+ int additiveType = AD_REPLACE;
+
+ /** Accumlative state */
+ public static final int AC_REPLACE = 0;
+ public static final int AC_SUM = 1;
+
+ int accumulateType = AC_REPLACE;
+
+ /** Creates a new instance of AnimateEle */
+ public AnimationElement()
+ {
+ }
+
+ public static String animationElementToString(int attrValue)
+ {
+ switch (attrValue)
+ {
+ case AT_CSS:
+ return "CSS";
+ case AT_XML:
+ return "XML";
+ case AT_AUTO:
+ return "AUTO";
+ default:
+ throw new RuntimeException("Unknown element type");
+ }
+ }
+
+ public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
+ {
+ //Load style string
+ super.loaderStartElement(helper, attrs, parent);
+
+ attribName = attrs.getValue("attributeName");
+ String attribType = attrs.getValue("attributeType");
+ if (attribType != null)
+ {
+ attribType = attribType.toLowerCase();
+ if (attribType.equals("css")) this.attribType = AT_CSS;
+ else if (attribType.equals("xml")) this.attribType = AT_XML;
+ }
+
+ String beginTime = attrs.getValue("begin");
+ String durTime = attrs.getValue("dur");
+ String endTime = attrs.getValue("end");
+
+ try
+ {
+ if (beginTime != null)
+ {
+ helper.animTimeParser.ReInit(new StringReader(beginTime));
+ this.beginTime = helper.animTimeParser.Expr();
+ this.beginTime.setParentElement(this);
+ }
+
+ if (durTime != null)
+ {
+ helper.animTimeParser.ReInit(new StringReader(durTime));
+ this.durTime = helper.animTimeParser.Expr();
+ this.durTime.setParentElement(this);
+ }
+
+ if (endTime != null)
+ {
+ helper.animTimeParser.ReInit(new StringReader(endTime));
+ this.endTime = helper.animTimeParser.Expr();
+ this.endTime.setParentElement(this);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new SAXException(e);
+ }
+
+// this.beginTime = TimeBase.parseTime(beginTime);
+// this.durTime = TimeBase.parseTime(durTime);
+// this.endTime = TimeBase.parseTime(endTime);
+
+ String fill = attrs.getValue("fill");
+
+ if (fill != null)
+ {
+ if (fill.equals("remove")) this.fillType = FT_REMOVE;
+ if (fill.equals("freeze")) this.fillType = FT_FREEZE;
+ if (fill.equals("hold")) this.fillType = FT_HOLD;
+ if (fill.equals("transiton")) this.fillType = FT_TRANSITION;
+ if (fill.equals("auto")) this.fillType = FT_AUTO;
+ if (fill.equals("default")) this.fillType = FT_DEFAULT;
+ }
+
+ String additiveStrn = attrs.getValue("additive");
+
+ if (additiveStrn != null)
+ {
+ if (additiveStrn.equals("replace")) this.additiveType = AD_REPLACE;
+ if (additiveStrn.equals("sum")) this.additiveType = AD_SUM;
+ }
+
+ String accumulateStrn = attrs.getValue("accumulate");
+
+ if (accumulateStrn != null)
+ {
+ if (accumulateStrn.equals("replace")) this.accumulateType = AC_REPLACE;
+ if (accumulateStrn.equals("sum")) this.accumulateType = AC_SUM;
+ }
+ }
+
+ public String getAttribName() { return attribName; }
+ public int getAttribType() { return attribType; }
+ public int getAdditiveType() { return additiveType; }
+ public int getAccumulateType() { return accumulateType; }
+
+ public void evalParametric(AnimationTimeEval state, double curTime)
+ {
+ evalParametric(state, curTime, Double.NaN, Double.NaN);
+ }
+
+ /**
+ * Compares current time to start and end times and determines what degree
+ * of time interpolation this track currently represents. Returns
+ * Float.NaN if this track cannot be evaluated at the passed time (ie,
+ * it is before or past the end of the track, or it depends upon
+ * an unknown event)
+ * @param state - A structure that will be filled with information
+ * regarding the applicability of this animatoin element at the passed
+ * time.
+ * @param curTime - Current time in seconds
+ * @param repeatCount - Optional number of repetitions of length 'dur' to
+ * do. Set to Double.NaN to not consider this in the calculation.
+ * @param repeatDur - Optional amoun tof time to repeat the animaiton.
+ * Set to Double.NaN to not consider this in the calculation.
+ */
+ protected void evalParametric(AnimationTimeEval state, double curTime, double repeatCount, double repeatDur)
+ {
+ double begin = (beginTime == null) ? 0 : beginTime.evalTime();
+ if (Double.isNaN(begin) || begin > curTime)
+ {
+ state.set(Double.NaN, 0);
+ return;
+ }
+
+ double dur = (durTime == null) ? Double.NaN : durTime.evalTime();
+ if (Double.isNaN(dur))
+ {
+ state.set(Double.NaN, 0);
+ return;
+ }
+
+ //Determine end point of this animation
+ double end = (endTime == null) ? Double.NaN : endTime.evalTime();
+ double repeat;
+// if (Double.isNaN(repeatDur))
+// {
+// repeatDur = dur;
+// }
+ if (Double.isNaN(repeatCount) && Double.isNaN(repeatDur))
+ {
+ repeat = Double.NaN;
+ }
+ else
+ {
+ repeat = Math.min(
+ Double.isNaN(repeatCount) ? Double.POSITIVE_INFINITY : dur * repeatCount,
+ Double.isNaN(repeatDur) ? Double.POSITIVE_INFINITY : repeatDur);
+ }
+ if (Double.isNaN(repeat) && Double.isNaN(end))
+ {
+ //If neither and end point nor a repeat is specified, end point is
+ // implied by duration.
+ end = begin + dur;
+ }
+
+ double finishTime;
+ if (Double.isNaN(end))
+ {
+ finishTime = begin + repeat;
+ }
+ else if (Double.isNaN(repeat))
+ {
+ finishTime = end;
+ }
+ else
+ {
+ finishTime = Math.min(end, repeat);
+ }
+
+ double evalTime = Math.min(curTime, finishTime);
+// if (curTime > finishTime) evalTime = finishTime;
+
+
+// double evalTime = curTime;
+
+// boolean pastEnd = curTime > evalTime;
+
+// if (!Double.isNaN(end) && curTime > end) { pastEnd = true; evalTime = Math.min(evalTime, end); }
+// if (!Double.isNaN(repeat) && curTime > repeat) { pastEnd = true; evalTime = Math.min(evalTime, repeat); }
+
+ double ratio = (evalTime - begin) / dur;
+ int rep = (int)ratio;
+ double interp = ratio - rep;
+
+ //Adjust for roundoff
+ if (interp < 0.00001) interp = 0;
+
+// state.set(interp, rep);
+// if (!pastEnd)
+// {
+// state.set(interp, rep, false);
+// return;
+// }
+
+ //If we are still within the clip, return value
+ if (curTime == evalTime)
+ {
+ state.set(interp, rep);
+ return;
+ }
+
+ //We are past end of clip. Determine to clamp or ignore.
+ switch (fillType)
+ {
+ default:
+ case FT_REMOVE:
+ case FT_AUTO:
+ case FT_DEFAULT:
+ state.set(Double.NaN, rep);
+ return;
+ case FT_FREEZE:
+ case FT_HOLD:
+ case FT_TRANSITION:
+ state.set(interp == 0 ? 1 : interp, rep);
+ return;
+ }
+
+ }
+
+ double evalStartTime()
+ {
+ return beginTime == null ? Double.NaN : beginTime.evalTime();
+ }
+
+ double evalDurTime()
+ {
+ return durTime == null ? Double.NaN : durTime.evalTime();
+ }
+
+ /**
+ * Evaluates the ending time of this element. Returns 0 if not specified.
+ *
+ * @see hasEndTime
+ */
+ double evalEndTime()
+ {
+ return endTime == null ? Double.NaN : endTime.evalTime();
+ }
+
+ /**
+ * Checks to see if an end time has been specified for this element.
+ */
+ boolean hasEndTime() { return endTime != null; }
+
+ /**
+ * Updates all attributes in this diagram associated with a time event.
+ * Ie, all attributes with track information.
+ * @return - true if this node has changed state as a result of the time
+ * update
+ */
+ public boolean updateTime(double curTime)
+ {
+ //Animation elements to not change with time
+ return false;
+ }}