Patch against rev 98 of https://svn.java.net/svn/svgsalamander~svn/trunk. It strips some classes, that aren't needed (basically animation and gui) and removes dependencies. The only purpose of this patch is to reduce binary download size for JOSM users. Index: core/src/com/kitfox/svg/animation/Animate.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/Animate.java 2012-06-17 23:56:57.664545050 +0200 @@ -0,0 +1,419 @@ +/* + * Animate.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:51 AM + */ + +package com.kitfox.svg.animation; + +import com.kitfox.svg.SVGElement; +import com.kitfox.svg.SVGException; +import com.kitfox.svg.SVGLoaderHelper; +import com.kitfox.svg.animation.parser.AnimTimeParser; +import com.kitfox.svg.xml.ColorTable; +import com.kitfox.svg.xml.StyleAttribute; +import com.kitfox.svg.xml.XMLParseUtil; +import java.awt.Color; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.PathIterator; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + + +/** + * Animate is a really annoying morphic tag that could represent a real value, + * a color or a path + * + * @author Mark McKay + * @author Mark McKay + */ +public class Animate extends AnimateBase implements AnimateColorIface +{ +// StyleAttribute retAttrib = new StyleAttribute + public static final int DT_REAL = 0; + public static final int DT_COLOR = 1; + public static final int DT_PATH = 2; + int dataType = DT_REAL; + + protected double fromValue = Double.NaN; + protected double toValue = Double.NaN; + protected double byValue = Double.NaN; + protected double[] valuesValue; + + protected Color fromColor = null; + protected Color toColor = null; + + protected GeneralPath fromPath = null; + protected GeneralPath toPath = null; + + /** Creates a new instance of Animate */ + public Animate() + { + } + + public int getDataType() + { + return dataType; + } + + public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException + { + //Load style string + super.loaderStartElement(helper, attrs, parent); + + String strn = attrs.getValue("from"); + if (strn != null) + { + if (XMLParseUtil.isDouble(strn)) + { + fromValue = XMLParseUtil.parseDouble(strn); + } +// else if (attrs.getValue("attributeName").equals("d")) +// { +// fromPath = this.buildPath(strn, GeneralPath.WIND_EVEN_ODD); +// dataType = DT_PATH; +// } + else + { + fromColor = ColorTable.parseColor(strn); + if (fromColor == null) + { + //Try path + fromPath = this.buildPath(strn, GeneralPath.WIND_EVEN_ODD); + dataType = DT_PATH; + } + else dataType = DT_COLOR; + } + } + + strn = attrs.getValue("to"); + if (strn != null) + { + if (XMLParseUtil.isDouble(strn)) + { + toValue = XMLParseUtil.parseDouble(strn); + } + else + { + toColor = ColorTable.parseColor(strn); + if (toColor == null) + { + //Try path + toPath = this.buildPath(strn, GeneralPath.WIND_EVEN_ODD); + dataType = DT_PATH; + } + else dataType = DT_COLOR; + } + } + + strn = attrs.getValue("by"); + try + { + if (strn != null) byValue = XMLParseUtil.parseDouble(strn); + } catch (Exception e) {} + + strn = attrs.getValue("values"); + try + { + if (strn != null) valuesValue = XMLParseUtil.parseDoubleList(strn); + } catch (Exception e) {} + } + + /** + * Evaluates this animation element for the passed interpolation time. Interp + * must be on [0..1]. + */ + public double eval(double interp) + { + boolean fromExists = !Double.isNaN(fromValue); + boolean toExists = !Double.isNaN(toValue); + boolean byExists = !Double.isNaN(byValue); + boolean valuesExists = valuesValue != null; + + if (valuesExists) + { + double sp = interp * valuesValue.length; + int ip = (int)sp; + double fp = sp - ip; + + int i0 = ip; + int i1 = ip + 1; + + if (i0 < 0) return valuesValue[0]; + if (i1 >= valuesValue.length) return valuesValue[valuesValue.length - 1]; + return valuesValue[i0] * (1 - fp) + valuesValue[i1] * fp; + } + else if (fromExists && toExists) + { + return toValue * interp + fromValue * (1.0 - interp); + } + else if (fromExists && byExists) + { + return fromValue + byValue * interp; + } + else if (toExists && byExists) + { + return toValue - byValue * (1.0 - interp); + } + else if (byExists) + { + return byValue * interp; + } + + //Should not reach this line + throw new RuntimeException("Animate tag could not be evalutated - insufficient arguements"); + } + + public Color evalColor(double interp) + { + if (fromColor == null && toColor != null) + { + float[] toCol = new float[3]; + toColor.getColorComponents(toCol); + return new Color(toCol[0] * (float)interp, + toCol[1] * (float)interp, + toCol[2] * (float)interp); + } + else if (fromColor != null && toColor != null) + { + float nInterp = 1 - (float)interp; + + float[] fromCol = new float[3]; + float[] toCol = new float[3]; + fromColor.getColorComponents(fromCol); + toColor.getColorComponents(toCol); + return new Color(fromCol[0] * nInterp + toCol[0] * (float)interp, + fromCol[1] * nInterp + toCol[1] * (float)interp, + fromCol[2] * nInterp + toCol[2] * (float)interp); + } + + throw new RuntimeException("Animate tag could not be evalutated - insufficient arguements"); + } + + public GeneralPath evalPath(double interp) + { + if (fromPath == null && toPath != null) + { + PathIterator itTo = toPath.getPathIterator(new AffineTransform()); + + GeneralPath midPath = new GeneralPath(); + float[] coordsTo = new float[6]; + + for (; !itTo.isDone(); itTo.next()) + { + int segTo = itTo.currentSegment(coordsTo); + + switch (segTo) + { + case PathIterator.SEG_CLOSE: + midPath.closePath(); + break; + case PathIterator.SEG_CUBICTO: + midPath.curveTo( + (float)(coordsTo[0] * interp), + (float)(coordsTo[1] * interp), + (float)(coordsTo[2] * interp), + (float)(coordsTo[3] * interp), + (float)(coordsTo[4] * interp), + (float)(coordsTo[5] * interp) + ); + break; + case PathIterator.SEG_LINETO: + midPath.lineTo( + (float)(coordsTo[0] * interp), + (float)(coordsTo[1] * interp) + ); + break; + case PathIterator.SEG_MOVETO: + midPath.moveTo( + (float)(coordsTo[0] * interp), + (float)(coordsTo[1] * interp) + ); + break; + case PathIterator.SEG_QUADTO: + midPath.quadTo( + (float)(coordsTo[0] * interp), + (float)(coordsTo[1] * interp), + (float)(coordsTo[2] * interp), + (float)(coordsTo[3] * interp) + ); + break; + } + } + + return midPath; + } + else if (toPath != null) + { + PathIterator itFrom = fromPath.getPathIterator(new AffineTransform()); + PathIterator itTo = toPath.getPathIterator(new AffineTransform()); + + GeneralPath midPath = new GeneralPath(); + float[] coordsFrom = new float[6]; + float[] coordsTo = new float[6]; + + for (; !itFrom.isDone(); itFrom.next()) + { + int segFrom = itFrom.currentSegment(coordsFrom); + int segTo = itTo.currentSegment(coordsTo); + + if (segFrom != segTo) + { + throw new RuntimeException("Path shape mismatch"); + } + + switch (segFrom) + { + case PathIterator.SEG_CLOSE: + midPath.closePath(); + break; + case PathIterator.SEG_CUBICTO: + midPath.curveTo( + (float)(coordsFrom[0] * (1 - interp) + coordsTo[0] * interp), + (float)(coordsFrom[1] * (1 - interp) + coordsTo[1] * interp), + (float)(coordsFrom[2] * (1 - interp) + coordsTo[2] * interp), + (float)(coordsFrom[3] * (1 - interp) + coordsTo[3] * interp), + (float)(coordsFrom[4] * (1 - interp) + coordsTo[4] * interp), + (float)(coordsFrom[5] * (1 - interp) + coordsTo[5] * interp) + ); + break; + case PathIterator.SEG_LINETO: + midPath.lineTo( + (float)(coordsFrom[0] * (1 - interp) + coordsTo[0] * interp), + (float)(coordsFrom[1] * (1 - interp) + coordsTo[1] * interp) + ); + break; + case PathIterator.SEG_MOVETO: + midPath.moveTo( + (float)(coordsFrom[0] * (1 - interp) + coordsTo[0] * interp), + (float)(coordsFrom[1] * (1 - interp) + coordsTo[1] * interp) + ); + break; + case PathIterator.SEG_QUADTO: + midPath.quadTo( + (float)(coordsFrom[0] * (1 - interp) + coordsTo[0] * interp), + (float)(coordsFrom[1] * (1 - interp) + coordsTo[1] * interp), + (float)(coordsFrom[2] * (1 - interp) + coordsTo[2] * interp), + (float)(coordsFrom[3] * (1 - interp) + coordsTo[3] * interp) + ); + break; + } + } + + return midPath; + } + + throw new RuntimeException("Animate tag could not be evalutated - insufficient arguements"); + } + + /** + * If this element is being accumulated, detemine the delta to accumulate by + */ + public double repeatSkipSize(int reps) + { + boolean fromExists = !Double.isNaN(fromValue); + boolean toExists = !Double.isNaN(toValue); + boolean byExists = !Double.isNaN(byValue); + + if (fromExists && toExists) + { + return (toValue - fromValue) * reps; + } + else if (fromExists && byExists) + { + return (fromValue + byValue) * reps; + } + else if (toExists && byExists) + { + return toValue * reps; + } + else if (byExists) + { + return byValue * reps; + } + + //Should not reach this line + return 0; + } + + protected void rebuild(AnimTimeParser animTimeParser) throws SVGException + { + super.rebuild(animTimeParser); + + StyleAttribute sty = new StyleAttribute(); + + if (getPres(sty.setName("from"))) + { + String strn = sty.getStringValue(); + if (XMLParseUtil.isDouble(strn)) + { + fromValue = XMLParseUtil.parseDouble(strn); + } + else + { + fromColor = ColorTable.parseColor(strn); + if (fromColor == null) + { + //Try path + fromPath = this.buildPath(strn, GeneralPath.WIND_EVEN_ODD); + dataType = DT_PATH; + } + else dataType = DT_COLOR; + } + } + + if (getPres(sty.setName("to"))) + { + String strn = sty.getStringValue(); + if (XMLParseUtil.isDouble(strn)) + { + toValue = XMLParseUtil.parseDouble(strn); + } + else + { + toColor = ColorTable.parseColor(strn); + if (toColor == null) + { + //Try path + toPath = this.buildPath(strn, GeneralPath.WIND_EVEN_ODD); + dataType = DT_PATH; + } + else dataType = DT_COLOR; + } + } + + if (getPres(sty.setName("by"))) + { + String strn = sty.getStringValue(); + if (strn != null) byValue = XMLParseUtil.parseDouble(strn); + } + + if (getPres(sty.setName("values"))) + { + String strn = sty.getStringValue(); + if (strn != null) valuesValue = XMLParseUtil.parseDoubleList(strn); + } + } + +} Index: core/src/com/kitfox/svg/animation/AnimateBase.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/AnimateBase.java 2012-06-17 23:56:57.664545050 +0200 @@ -0,0 +1,133 @@ +/* + * Animate.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:51 AM + */ + +package com.kitfox.svg.animation; + +import com.kitfox.svg.SVGElement; +import com.kitfox.svg.SVGException; +import com.kitfox.svg.SVGLoaderHelper; +import com.kitfox.svg.animation.parser.AnimTimeParser; +import com.kitfox.svg.animation.parser.ParseException; +import com.kitfox.svg.xml.StyleAttribute; +import java.io.StringReader; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +/** + * @author Mark McKay + * @author Mark McKay + */ +abstract public class AnimateBase extends AnimationElement +{ + protected double repeatCount = Double.NaN; + protected TimeBase repeatDur; + + /** Creates a new instance of Animate */ + public AnimateBase() + { + } + + public void evalParametric(AnimationTimeEval state, double curTime) + { + evalParametric(state, curTime, repeatCount, repeatDur == null ? Double.NaN : repeatDur.evalTime()); + } + + public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException + { + //Load style string + super.loaderStartElement(helper, attrs, parent); + + String repeatDurTime = attrs.getValue("repeatDur"); + + try + { + if (repeatDurTime != null) + { + helper.animTimeParser.ReInit(new StringReader(repeatDurTime)); + this.repeatDur = helper.animTimeParser.Expr(); + this.repeatDur.setParentElement(this); + } + } + catch (Exception e) + { + throw new SAXException(e); + } + + String strn = attrs.getValue("repeatCount"); + if (strn == null) + { + repeatCount = 1; + } + else if ("indefinite".equals(strn)) + { + repeatCount = Double.POSITIVE_INFINITY; + } + else + { + try { repeatCount = Double.parseDouble(strn); } + catch (Exception e) { repeatCount = Double.NaN; } + } + } + + protected void rebuild(AnimTimeParser animTimeParser) throws SVGException + { + super.rebuild(animTimeParser); + + StyleAttribute sty = new StyleAttribute(); + + if (getPres(sty.setName("repeatDur"))) + { + String strn = sty.getStringValue(); + if (strn != null) + { + animTimeParser.ReInit(new StringReader(strn)); + try { + this.repeatDur = animTimeParser.Expr(); + } catch (ParseException ex) { + ex.printStackTrace(); + } + } + } + + if (getPres(sty.setName("repeatCount"))) + { + String strn = sty.getStringValue(); + if (strn == null) + { + repeatCount = 1; + } + else if ("indefinite".equals(strn)) + { + repeatCount = Double.POSITIVE_INFINITY; + } + else + { + try { repeatCount = Double.parseDouble(strn); } + catch (Exception e) { repeatCount = Double.NaN; } + } + } + } +} Index: core/src/com/kitfox/svg/animation/AnimateColor.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/AnimateColor.java 2012-06-17 23:56:57.672545050 +0200 @@ -0,0 +1,105 @@ +/* + * Animate.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:51 AM + */ + +package com.kitfox.svg.animation; + +import com.kitfox.svg.SVGElement; +import com.kitfox.svg.SVGException; +import com.kitfox.svg.SVGLoaderHelper; +import com.kitfox.svg.animation.parser.AnimTimeParser; +import com.kitfox.svg.xml.ColorTable; +import com.kitfox.svg.xml.StyleAttribute; +import java.awt.Color; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + + +/** + * @author Mark McKay + * @author Mark McKay + */ +public class AnimateColor extends AnimateBase implements AnimateColorIface +{ + + protected Color fromValue; + protected Color toValue; + + /** Creates a new instance of Animate */ + public AnimateColor() + { + } + + public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException + { + //Load style string + super.loaderStartElement(helper, attrs, parent); + + String strn = attrs.getValue("from"); + fromValue = ColorTable.parseColor(strn); + + strn = attrs.getValue("to"); + toValue = ColorTable.parseColor(strn); + } + + + /** + * Evaluates this animation element for the passed interpolation time. Interp + * must be on [0..1]. + */ + public Color evalColor(double interp) + { + int r1 = fromValue.getRed(); + int g1 = fromValue.getGreen(); + int b1 = fromValue.getBlue(); + int r2 = toValue.getRed(); + int g2 = toValue.getGreen(); + int b2 = toValue.getBlue(); + double invInterp = 1.0 - interp; + + return new Color((int)(r1 * invInterp + r2 * interp), + (int)(g1 * invInterp + g2 * interp), + (int)(b1 * invInterp + b2 * interp)); + } + + protected void rebuild(AnimTimeParser animTimeParser) throws SVGException + { + super.rebuild(animTimeParser); + + StyleAttribute sty = new StyleAttribute(); + + if (getPres(sty.setName("from"))) + { + String strn = sty.getStringValue(); + fromValue = ColorTable.parseColor(strn); + } + + if (getPres(sty.setName("to"))) + { + String strn = sty.getStringValue(); + toValue = ColorTable.parseColor(strn); + } + } +} Index: core/src/com/kitfox/svg/animation/AnimateColorIface.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/AnimateColorIface.java 2012-06-17 23:56:57.672545050 +0200 @@ -0,0 +1,38 @@ +/* + * AnimateColorIface.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 January 16, 2005, 6:24 AM + */ + +package com.kitfox.svg.animation; + +import java.awt.*; + +/** + * + * @author kitfox + */ +public interface AnimateColorIface +{ + public Color evalColor(double interp); +} Index: core/src/com/kitfox/svg/animation/AnimateMotion.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/AnimateMotion.java 2012-06-17 23:56:57.672545050 +0200 @@ -0,0 +1,282 @@ +/* + * Animate.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:51 AM + */ + +package com.kitfox.svg.animation; + +import com.kitfox.svg.SVGElement; +import com.kitfox.svg.SVGException; +import com.kitfox.svg.SVGLoaderHelper; +import com.kitfox.svg.animation.parser.AnimTimeParser; +import com.kitfox.svg.xml.StyleAttribute; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + + +/** + * @author Mark McKay + * @author Mark McKay + */ +public class AnimateMotion extends AnimateXform +{ + static final Matcher matchPoint = Pattern.compile("\\s*(\\d+)[^\\d]+(\\d+)\\s*").matcher(""); + +// protected double fromValue; +// protected double toValue; + GeneralPath path; + int rotateType = RT_ANGLE; + double rotate; //Static angle to rotate by + + public static final int RT_ANGLE = 0; //Rotate by constant 'rotate' degrees + public static final int RT_AUTO = 1; //Rotate to reflect tangent of position on path + + final ArrayList bezierSegs = new ArrayList(); + double curveLength; + + /** Creates a new instance of Animate */ + public AnimateMotion() + { + } + + public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException + { + //Load style string + super.loaderStartElement(helper, attrs, parent); + + //Motion element implies animating the transform element + if (attribName == null) + { + attribName = "transform"; + attribType = AT_AUTO; + additiveType = AD_SUM; + } + + + String path = attrs.getValue("path"); + if (path != null) + { + this.path = buildPath(path, GeneralPath.WIND_NON_ZERO); + } + + //Now parse rotation style + String rotate = attrs.getValue("rotate"); + if (rotate != null) + { + if (rotate.equals("auto")) + { + this.rotateType = RT_AUTO; + } + else + { + try { this.rotate = Math.toRadians(Float.parseFloat(rotate)); } catch (Exception e) {} + } + } + + //Determine path + String from = attrs.getValue("from"); + String to = attrs.getValue("to"); + + buildPath(from, to); + } + + protected static void setPoint(Point2D.Float pt, String x, String y) + { + try { pt.x = Float.parseFloat(x); } catch (Exception e) {}; + + try { pt.y = Float.parseFloat(y); } catch (Exception e) {}; + } + + private void buildPath(String from, String to) + { + if (from != null && to != null) + { + Point2D.Float ptFrom = new Point2D.Float(), ptTo = new Point2D.Float(); + + matchPoint.reset(from); + if (matchPoint.matches()) + { + setPoint(ptFrom, matchPoint.group(1), matchPoint.group(2)); + } + + matchPoint.reset(to); + if (matchPoint.matches()) + { + setPoint(ptFrom, matchPoint.group(1), matchPoint.group(2)); + } + + if (ptFrom != null && ptTo != null) + { + path = new GeneralPath(); + path.moveTo(ptFrom.x, ptFrom.y); + path.lineTo(ptTo.x, ptTo.y); + } + } + + paramaterizePath(); + } + + private void paramaterizePath() + { + bezierSegs.clear(); + curveLength = 0; + + double[] coords = new double[6]; + double sx = 0, sy = 0; + + for (PathIterator pathIt = path.getPathIterator(new AffineTransform()); !pathIt.isDone(); pathIt.next()) + { + Bezier bezier = null; + + int segType = pathIt.currentSegment(coords); + + switch (segType) + { + case PathIterator.SEG_LINETO: + { + bezier = new Bezier(sx, sy, coords, 1); + sx = coords[0]; + sy = coords[1]; + break; + } + case PathIterator.SEG_QUADTO: + { + bezier = new Bezier(sx, sy, coords, 2); + sx = coords[2]; + sy = coords[3]; + break; + } + case PathIterator.SEG_CUBICTO: + { + bezier = new Bezier(sx, sy, coords, 3); + sx = coords[4]; + sy = coords[5]; + break; + } + case PathIterator.SEG_MOVETO: + { + sx = coords[0]; + sy = coords[1]; + break; + } + case PathIterator.SEG_CLOSE: + //Do nothing + break; + + } + + if (bezier != null) + { + bezierSegs.add(bezier); + curveLength += bezier.getLength(); + } + } + } + + /** + * Evaluates this animation element for the passed interpolation time. Interp + * must be on [0..1]. + */ + public AffineTransform eval(AffineTransform xform, double interp) + { + Point2D.Double point = new Point2D.Double(); + + if (interp >= 1) + { + Bezier last = (Bezier)bezierSegs.get(bezierSegs.size() - 1); + last.getFinalPoint(point); + xform.setToTranslation(point.x, point.y); + return xform; + } + + double curLength = curveLength * interp; + for (Iterator it = bezierSegs.iterator(); it.hasNext();) + { + Bezier bez = (Bezier)it.next(); + + double bezLength = bez.getLength(); + if (curLength < bezLength) + { + double param = curLength / bezLength; + bez.eval(param, point); + break; + } + + curLength -= bezLength; + } + + xform.setToTranslation(point.x, point.y); + + return xform; + } + + + protected void rebuild(AnimTimeParser animTimeParser) throws SVGException + { + super.rebuild(animTimeParser); + + StyleAttribute sty = new StyleAttribute(); + + if (getPres(sty.setName("path"))) + { + String strn = sty.getStringValue(); + this.path = buildPath(strn, GeneralPath.WIND_NON_ZERO); + } + + if (getPres(sty.setName("rotate"))) + { + String strn = sty.getStringValue(); + if (strn.equals("auto")) + { + this.rotateType = RT_AUTO; + } + else + { + try { this.rotate = Math.toRadians(Float.parseFloat(strn)); } catch (Exception e) {} + } + } + + String from = null; + if (getPres(sty.setName("from"))) + { + from = sty.getStringValue(); + } + + String to = null; + if (getPres(sty.setName("to"))) + { + to = sty.getStringValue(); + } + + buildPath(from, to); + } +} Index: core/src/com/kitfox/svg/animation/AnimateTransform.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/AnimateTransform.java 2012-06-17 23:56:57.676545050 +0200 @@ -0,0 +1,302 @@ +/* + * Animate.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:51 AM + */ + +package com.kitfox.svg.animation; + +import com.kitfox.svg.SVGElement; +import com.kitfox.svg.SVGException; +import com.kitfox.svg.SVGLoaderHelper; +import com.kitfox.svg.animation.parser.AnimTimeParser; +import com.kitfox.svg.xml.StyleAttribute; +import com.kitfox.svg.xml.XMLParseUtil; +import java.awt.geom.AffineTransform; +import java.util.regex.Pattern; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + + +/** + * @author Mark McKay + * @author Mark McKay + */ +public class AnimateTransform extends AnimateXform +{ +// protected AffineTransform fromValue; +// protected AffineTransform toValue; +// protected double[] fromValue; //Transform parameters +// protected double[] toValue; + protected double[][] values; + protected double[] keyTimes; + + public static final int AT_REPLACE = 0; + public static final int AT_SUM = 1; + + protected int additive = AT_REPLACE; + + public static final int TR_TRANSLATE = 0; + public static final int TR_ROTATE = 1; + public static final int TR_SCALE = 2; + public static final int TR_SKEWY = 3; + public static final int TR_SKEWX = 4; + public static final int TR_INVALID = 5; + + protected int xformType = TR_INVALID; + + /** Creates a new instance of Animate */ + public AnimateTransform() + { + } + + public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException + { + //Load style string + super.loaderStartElement(helper, attrs, parent); + + //Type of matrix of transform. Should be one of the known names used to + // define matrix transforms + // valid types: translate, scale, rotate, skewX, skewY + // 'matrix' not valid for animation + String type = attrs.getValue("type").toLowerCase(); + if (type.equals("translate")) xformType = TR_TRANSLATE; + if (type.equals("rotate")) xformType = TR_ROTATE; + if (type.equals("scale")) xformType = TR_SCALE; + if (type.equals("skewx")) xformType = TR_SKEWX; + if (type.equals("skewy")) xformType = TR_SKEWY; + + String fromStrn = attrs.getValue("from"); + String toStrn = attrs.getValue("to"); + if (fromStrn != null && toStrn != null) + { + //fromValue = parseSingleTransform(type + "(" + strn + ")"); + double[] fromValue = XMLParseUtil.parseDoubleList(fromStrn); + fromValue = validate(fromValue); + + // toValue = parseSingleTransform(type + "(" + strn + ")"); + double[] toValue = XMLParseUtil.parseDoubleList(toStrn); + toValue = validate(toValue); + + values = new double[][]{fromValue, toValue}; + keyTimes = new double[]{0, 1}; + } + + String keyTimeStrn = attrs.getValue("keyTimes"); + String valuesStrn = attrs.getValue("values"); + if (keyTimeStrn != null && valuesStrn != null) + { + keyTimes = XMLParseUtil.parseDoubleList(keyTimeStrn); + + String[] valueList = Pattern.compile(";").split(valuesStrn); + values = new double[valueList.length][]; + for (int i = 0; i < valueList.length; i++) + { + double[] list = XMLParseUtil.parseDoubleList(valueList[i]); + values[i] = validate(list); + } + } + + //Check our additive state + String additive = attrs.getValue("additive"); + if (additive != null) + { + if (additive.equals("sum")) this.additive = AT_SUM; + } + } + + /** + * Check list size against current xform type and ensure list + * is expanded to a standard list size + */ + private double[] validate(double[] paramList) + { + switch (xformType) + { + case TR_SCALE: + { + if (paramList == null) + { + paramList = new double[]{1, 1}; + } + else if (paramList.length == 1) + { + paramList = new double[]{paramList[0], paramList[0]}; + +// double[] tmp = paramList; +// paramList = new double[2]; +// paramList[0] = paramList[1] = tmp[0]; + } + } + } + + return paramList; + } + + /** + * Evaluates this animation element for the passed interpolation time. Interp + * must be on [0..1]. + */ + public AffineTransform eval(AffineTransform xform, double interp) + { + int idx = 0; + for (; idx < keyTimes.length - 1; idx++) + { + if (interp >= keyTimes[idx]) + { + idx--; + if (idx < 0) idx = 0; + break; + } + } + + double spanStartTime = keyTimes[idx]; + double spanEndTime = keyTimes[idx + 1]; +// double span = spanStartTime - spanEndTime; + + interp = (interp - spanStartTime) / (spanEndTime - spanStartTime); + double[] fromValue = values[idx]; + double[] toValue = values[idx + 1]; + + switch (xformType) + { + case TR_TRANSLATE: + { + double x = (1.0 - interp) * fromValue[0] + interp * toValue[0]; + double y = (1.0 - interp) * fromValue[1] + interp * toValue[1]; + xform.setToTranslation(x, y); + break; + } + case TR_ROTATE: + { + double x1 = fromValue.length == 3 ? fromValue[1] : 0; + double y1 = fromValue.length == 3 ? fromValue[2] : 0; + double x2 = toValue.length == 3 ? toValue[1] : 0; + double y2 = toValue.length == 3 ? toValue[2] : 0; + + double theta = (1.0 - interp) * fromValue[0] + interp * toValue[0]; + double x = (1.0 - interp) * x1 + interp * x2; + double y = (1.0 - interp) * y1 + interp * y2; + xform.setToRotation(Math.toRadians(theta), x, y); + break; + } + case TR_SCALE: + { + double x = (1.0 - interp) * fromValue[0] + interp * toValue[0]; + double y = (1.0 - interp) * fromValue[1] + interp * toValue[1]; + xform.setToScale(x, y); + break; + } + case TR_SKEWX: + { + double x = (1.0 - interp) * fromValue[0] + interp * toValue[0]; + xform.setToShear(Math.toRadians(x), 0.0); + break; + } + case TR_SKEWY: + { + double y = (1.0 - interp) * fromValue[0] + interp * toValue[0]; + xform.setToShear(0.0, Math.toRadians(y)); + break; + } + default: + xform.setToIdentity(); + break; + } + + return xform; + } + + protected void rebuild(AnimTimeParser animTimeParser) throws SVGException + { + super.rebuild(animTimeParser); + + StyleAttribute sty = new StyleAttribute(); + + if (getPres(sty.setName("type"))) + { + String strn = sty.getStringValue().toLowerCase(); + if (strn.equals("translate")) xformType = TR_TRANSLATE; + if (strn.equals("rotate")) xformType = TR_ROTATE; + if (strn.equals("scale")) xformType = TR_SCALE; + if (strn.equals("skewx")) xformType = TR_SKEWX; + if (strn.equals("skewy")) xformType = TR_SKEWY; + } + + String fromStrn = null; + if (getPres(sty.setName("from"))) + { + fromStrn = sty.getStringValue(); + } + + String toStrn = null; + if (getPres(sty.setName("to"))) + { + toStrn = sty.getStringValue(); + } + + if (fromStrn != null && toStrn != null) + { + double[] fromValue = XMLParseUtil.parseDoubleList(fromStrn); + fromValue = validate(fromValue); + + double[] toValue = XMLParseUtil.parseDoubleList(toStrn); + toValue = validate(toValue); + + values = new double[][]{fromValue, toValue}; + } + + String keyTimeStrn = null; + if (getPres(sty.setName("keyTimes"))) + { + keyTimeStrn = sty.getStringValue(); + } + + String valuesStrn = null; + if (getPres(sty.setName("values"))) + { + valuesStrn = sty.getStringValue(); + } + + if (keyTimeStrn != null && valuesStrn != null) + { + keyTimes = XMLParseUtil.parseDoubleList(keyTimeStrn); + + String[] valueList = Pattern.compile(";").split(valuesStrn); + values = new double[valueList.length][]; + for (int i = 0; i < valueList.length; i++) + { + double[] list = XMLParseUtil.parseDoubleList(valueList[i]); + values[i] = validate(list); + } + } + + //Check our additive state + + if (getPres(sty.setName("additive"))) + { + String strn = sty.getStringValue().toLowerCase(); + if (strn.equals("sum")) this.additive = AT_SUM; + } + } +} Index: core/src/com/kitfox/svg/animation/AnimateXform.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/AnimateXform.java 2012-06-17 23:56:57.676545050 +0200 @@ -0,0 +1,54 @@ +/* + * AnimateXform.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 January 14, 2005, 6:46 AM + */ + +package com.kitfox.svg.animation; + +import com.kitfox.svg.SVGElement; +import com.kitfox.svg.SVGLoaderHelper; +import java.awt.geom.AffineTransform; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + + + +/** + * + * @author kitfox + */ +abstract public class AnimateXform extends AnimateBase +{ + public AnimateXform() + { + } + + public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException + { + super.loaderStartElement(helper, attrs, parent); + } + + abstract public AffineTransform eval(AffineTransform xform, double interp); + +} Index: core/src/com/kitfox/svg/animation/AnimationElement.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/AnimationElement.java 2012-06-17 23:56:57.676545050 +0200 @@ -0,0 +1,414 @@ +/* + * 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 com.kitfox.svg.SVGElement; +import com.kitfox.svg.SVGException; +import com.kitfox.svg.SVGLoaderHelper; +import com.kitfox.svg.animation.parser.AnimTimeParser; +import com.kitfox.svg.animation.parser.ParseException; +import com.kitfox.svg.xml.StyleAttribute; +import java.io.StringReader; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + + +/** + * @author Mark McKay + * @author Mark McKay + */ +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; + + /** More about the fill attribute */ + 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; + } + + public void rebuild() throws SVGException + { + AnimTimeParser animTimeParser = new AnimTimeParser(new StringReader("")); + + rebuild(animTimeParser); + } + + protected void rebuild(AnimTimeParser animTimeParser) throws SVGException + { + StyleAttribute sty = new StyleAttribute(); + + if (getPres(sty.setName("begin"))) + { + String newVal = sty.getStringValue(); + animTimeParser.ReInit(new StringReader(newVal)); + try { + this.beginTime = animTimeParser.Expr(); + } catch (ParseException ex) { + ex.printStackTrace(); + } + } + + if (getPres(sty.setName("dur"))) + { + String newVal = sty.getStringValue(); + animTimeParser.ReInit(new StringReader(newVal)); + try { + this.durTime = animTimeParser.Expr(); + } catch (ParseException ex) { + ex.printStackTrace(); + } + } + + if (getPres(sty.setName("end"))) + { + String newVal = sty.getStringValue(); + animTimeParser.ReInit(new StringReader(newVal)); + try { + this.endTime = animTimeParser.Expr(); + } catch (ParseException ex) { + ex.printStackTrace(); + } + } + + if (getPres(sty.setName("fill"))) + { + String newVal = sty.getStringValue(); + if (newVal.equals("remove")) this.fillType = FT_REMOVE; + if (newVal.equals("freeze")) this.fillType = FT_FREEZE; + if (newVal.equals("hold")) this.fillType = FT_HOLD; + if (newVal.equals("transiton")) this.fillType = FT_TRANSITION; + if (newVal.equals("auto")) this.fillType = FT_AUTO; + if (newVal.equals("default")) this.fillType = FT_DEFAULT; + } + + if (getPres(sty.setName("additive"))) + { + String newVal = sty.getStringValue(); + if (newVal.equals("replace")) this.additiveType = AD_REPLACE; + if (newVal.equals("sum")) this.additiveType = AD_SUM; + } + + if (getPres(sty.setName("accumulate"))) + { + String newVal = sty.getStringValue(); + if (newVal.equals("replace")) this.accumulateType = AC_REPLACE; + if (newVal.equals("sum")) this.accumulateType = AC_SUM; + } + + } +} Index: core/src/com/kitfox/svg/animation/AnimationTimeEval.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/AnimationTimeEval.java 2012-06-17 23:56:57.676545050 +0200 @@ -0,0 +1,65 @@ +/* + * AnimateTimeEval.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 September 21, 2004, 1:31 PM + */ + +package com.kitfox.svg.animation; + +/** + * + * @author kitfox + */ +public class AnimationTimeEval +{ + /** + * Value on [0..1] representing the interpolation value of queried animation + * element, or Double.NaN if element does not provide a valid evalutaion + */ + public double interp; + + /** + * Number of completed repetitions + */ + public int rep; + + /** + * True if this evaluation is in a frozen state; ie, past the end of the + * track and held in the "freeze" state. + */ +// public boolean pastEnd; + + /** Creates a new instance of AnimateTimeEval */ + public AnimationTimeEval() + { + } + +// public void set(double interp, int rep, boolean pastEnd) + public void set(double interp, int rep) + { + this.interp = interp; + this.rep = rep; +// this.pastEnd = pastEnd; + } +} Index: core/src/com/kitfox/svg/animation/Bezier.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/Bezier.java 2012-06-17 23:56:57.680545050 +0200 @@ -0,0 +1,201 @@ +/* + * Bezier.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 January 14, 2005, 4:08 AM + */ + +package com.kitfox.svg.animation; + +import java.awt.geom.*; + +/** + * http://mathworld.wolfram.com/BezierCurve.html + * @author kitfox + */ +public class Bezier +{ + double length; + double[] coord; + + public Bezier(double sx, double sy, double[] coords, int numCoords) + { + setCoords(sx, sy, coords, numCoords); + } + + public void setCoords(double sx, double sy, double[] coords, int numCoords) + { + coord = new double[numCoords * 2 + 2]; + coord[0] = sx; + coord[1] = sy; + for (int i = 0; i < numCoords; i++) + { + coord[i * 2 + 2] = coords[i * 2]; + coord[i * 2 + 3] = coords[i * 2 + 1]; + } + + calcLength(); + } + + /** + * Retuns aproximation of the length of the bezier + */ + public double getLength() + { + return length; + } + + private void calcLength() + { + length = 0; + for (int i = 2; i < coord.length; i += 2) + { + length += lineLength(coord[i - 2], coord[i - 1], coord[i], coord[i + 1]); + } + } + + private double lineLength(double x1, double y1, double x2, double y2) + { + double dx = x2 - x1, dy = y2 - y1; + return Math.sqrt(dx * dx + dy * dy); + } + + public Point2D.Double getFinalPoint(Point2D.Double point) + { + point.x = coord[coord.length - 2]; + point.y = coord[coord.length - 1]; + return point; + } + + public Point2D.Double eval(double param, Point2D.Double point) + { + point.x = 0; + point.y = 0; + int numKnots = coord.length / 2; + + for (int i = 0; i < numKnots; i++) + { + double scale = bernstein(numKnots - 1, i, param); + point.x += coord[i * 2] * scale; + point.y += coord[i * 2 + 1] * scale; + } + + return point; + } + + /** + * Calculates the bernstein polynomial for evaluating parametric bezier + * @param numKnots - one less than number of knots in this curve hull + * @param knotNo - knot we are evaluating Bernstein for + * @param param - Parametric value we are evaluating at + */ + private double bernstein(int numKnots, int knotNo, double param) + { + double iParam = 1 - param; + //Faster evaluation for easy cases: + switch (numKnots) + { + case 0: + return 1; + case 1: + { + switch (knotNo) + { + case 0: + return iParam; + case 1: + return param; + } + break; + } + case 2: + { + switch (knotNo) + { + case 0: + return iParam * iParam; + case 1: + return 2 * iParam * param; + case 2: + return param * param; + } + break; + } + case 3: + { + switch (knotNo) + { + case 0: + return iParam * iParam * iParam; + case 1: + return 3 * iParam * iParam * param; + case 2: + return 3 * iParam * param * param; + case 3: + return param * param * param; + } + break; + } + } + + //If this bezier has more than four points, calculate bernstein the hard way + double retVal = 1; + for (int i = 0; i < knotNo; i++) + { + retVal *= param; + } + for (int i = 0; i < numKnots - knotNo; i++) + { + retVal *= iParam; + } + retVal *= choose(numKnots, knotNo); + + return retVal; + } + + + + private int choose(int num, int denom) + { + int denom2 = num - denom; + if (denom < denom2) + { + int tmp = denom; + denom = denom2; + denom2 = tmp; + } + + int prod = 1; + for (int i = num; i > denom; i--) + { + prod *= num; + } + + for (int i = 2; i <= denom2; i++) + { + prod /= i; + } + + return prod; + } +} Index: core/src/com/kitfox/svg/animation/SetSmil.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/SetSmil.java 2012-06-17 23:56:57.680545050 +0200 @@ -0,0 +1,73 @@ +/* + * Set.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:51 AM + */ + +package com.kitfox.svg.animation; + +import com.kitfox.svg.SVGElement; +import com.kitfox.svg.SVGException; +import com.kitfox.svg.SVGLoaderHelper; +import com.kitfox.svg.animation.parser.AnimTimeParser; +import com.kitfox.svg.xml.StyleAttribute; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + + +/** + * Set is used to set a textual value; most likely for a style element. + * + * @author Mark McKay + * @author Mark McKay + */ +public class SetSmil extends AnimationElement +{ + String toValue; + + /** Creates a new instance of Set */ + public SetSmil() + { + } + + public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException + { + //Load style string + super.loaderStartElement(helper, attrs, parent); + + toValue = attrs.getValue("to"); + } + + protected void rebuild(AnimTimeParser animTimeParser) throws SVGException + { + super.rebuild(animTimeParser); + + StyleAttribute sty = new StyleAttribute(); + + if (getPres(sty.setName("to"))) + { + String newVal = sty.getStringValue(); + toValue = newVal; + } + } +} Index: core/src/com/kitfox/svg/animation/TimeBase.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/TimeBase.java 2012-06-17 23:56:57.680545050 +0200 @@ -0,0 +1,99 @@ +/* + * TimeBase.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, 3:31 AM + */ + +package com.kitfox.svg.animation; + +import java.util.regex.*; + +/** + * SVG has a complicated way of specifying time. Potentially, a time could + * be represened as a summation of discrete times and times of other animation + * events. This provides a root for the many elements we will need to define + * time. + * + * @author Mark McKay + * @author Mark McKay + */ +abstract public class TimeBase +{ + static final Matcher matchIndefinite = Pattern.compile("\\s*indefinite\\s*").matcher(""); + static final Matcher matchUnitTime = Pattern.compile("\\s*([-+]?((\\d*\\.\\d+)|(\\d+))([-+]?[eE]\\d+)?)\\s*(h|min|s|ms)?\\s*").matcher(""); + + /* + public static TimeBase parseTime(String text) + { + if (text == null) return null; + + if (text.indexOf('+') == -1) + { + return parseTimeComponent(text); + } + + return new TimeCompound(text); + } + */ + + protected static TimeBase parseTimeComponent(String text) + { + matchIndefinite.reset(text); + if (matchIndefinite.matches()) return new TimeIndefinite(); + + matchUnitTime.reset(text); + if (matchUnitTime.matches()) + { + String val = matchUnitTime.group(1); + String units = matchUnitTime.group(6); + + double time = 0; + try { time = Double.parseDouble(val); } + catch (Exception e) {} + + if (units.equals("ms")) time *= .001; + else if (units.equals("min")) time *= 60; + else if (units.equals("h")) time *= 3600; + + return new TimeDiscrete(time); + } + + return null; + } + + /** + * Calculates the (greater than or equal to 0) time in seconds this + * time represents. If the time cannot be determined, returns + * Double.NaN. If this represents an infinte amount of time, returns + * Double.POSITIVE_INFINITY. + */ + abstract public double evalTime(); + + /** + * Some time elements need to refer to the animation element that contains + * them to evaluate correctly + */ + public void setParentElement(AnimationElement ele) + { + } +} Index: core/src/com/kitfox/svg/animation/TimeCompound.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/TimeCompound.java 2012-06-17 23:56:57.680545050 +0200 @@ -0,0 +1,84 @@ +/* + * TimeDiscrete.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, 3:33 AM + */ + +package com.kitfox.svg.animation; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Pattern; + + +/** + * This represents a summation of other time elements. It is used for complex + * timing events with offsets. + * + * @author Mark McKay + * @author Mark McKay + */ +public class TimeCompound extends TimeBase +{ + static final Pattern patPlus = Pattern.compile("\\+"); + + /** + * This is a list of times. This element's time is calculated as the greatest + * member that is less than the current time. + */ + final List componentTimes; + + private AnimationElement parent; + + /** Creates a new instance of TimeDiscrete */ + public TimeCompound(List timeBases) + { + componentTimes = Collections.unmodifiableList(timeBases); + } + + public double evalTime() + { + double agg = 0.0; + + for (Iterator it = componentTimes.iterator(); it.hasNext();) + { + TimeBase timeEle = (TimeBase)it.next(); + double time = timeEle.evalTime(); + agg += time; + } + + return agg; + } + + public void setParentElement(AnimationElement ele) + { + this.parent = ele; + + for (Iterator it = componentTimes.iterator(); it.hasNext();) + { + TimeBase timeEle = (TimeBase)it.next(); + timeEle.setParentElement(ele); + } + } +} Index: core/src/com/kitfox/svg/animation/TimeDiscrete.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/TimeDiscrete.java 2012-06-17 23:56:57.680545050 +0200 @@ -0,0 +1,51 @@ +/* + * TimeDiscrete.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, 3:33 AM + */ + +package com.kitfox.svg.animation; + +/** + * This is a time that represents a specific number of milliseconds + * + * @author Mark McKay + * @author Mark McKay + */ +public class TimeDiscrete extends TimeBase +{ + //Milliseconds of delay + double secs; + + /** Creates a new instance of TimeDiscrete */ + public TimeDiscrete(double secs) + { + this.secs = secs; + } + + public double evalTime() + { + return secs; + } + +} Index: core/src/com/kitfox/svg/animation/TimeIndefinite.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/TimeIndefinite.java 2012-06-17 23:56:57.680545050 +0200 @@ -0,0 +1,48 @@ +/* + * TimeDiscrete.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, 3:33 AM + */ + +package com.kitfox.svg.animation; + +/** + * This represents the indefinite (infinite) amount of time. + * + * @author Mark McKay + * @author Mark McKay + */ +public class TimeIndefinite extends TimeBase +{ + + /** Creates a new instance of TimeDiscrete */ + public TimeIndefinite() + { + } + + public double evalTime() + { + return Double.POSITIVE_INFINITY; + } + +} Index: core/src/com/kitfox/svg/animation/TimeLookup.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/TimeLookup.java 2012-06-17 23:56:57.684545050 +0200 @@ -0,0 +1,75 @@ +/* + * TimeDiscrete.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, 3:33 AM + */ + +package com.kitfox.svg.animation; + +/** + * This is a time that represents a specific number of milliseconds + * + * @author Mark McKay + * @author Mark McKay + */ +public class TimeLookup extends TimeBase +{ + /** + * This time can only be resolved in relation to it's parent + */ + private AnimationElement parent; + + /** + * Node this lookup acts upon + */ + String node; + + /** + * Event to evalutae on this node + */ + String event; + + /** + * Optional parameter used by some events + */ + String paramList; + + /** Creates a new instance of TimeDiscrete */ + public TimeLookup(AnimationElement parent, String node, String event, String paramList) + { + this.parent = parent; + this.node = node; + this.event = event; + this.paramList = paramList; + } + + public double evalTime() + { + return 0.0; + } + + public void setParentElement(AnimationElement ele) + { + parent = ele; + } +} Index: core/src/com/kitfox/svg/animation/TimeSum.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/TimeSum.java 2012-06-17 23:56:57.684545050 +0200 @@ -0,0 +1,60 @@ +/* + * TimeDiscrete.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, 3:33 AM + */ + +package com.kitfox.svg.animation; + +/** + * This is a time that represents a specific number of milliseconds + * + * @author Mark McKay + * @author Mark McKay + */ +public class TimeSum extends TimeBase +{ + //Milliseconds of delay + TimeBase t1; + TimeBase t2; + boolean add; + + /** Creates a new instance of TimeDiscrete */ + public TimeSum(TimeBase t1, TimeBase t2, boolean add) + { + this.t1 = t1; + this.t2 = t2; + this.add = add; + } + + public double evalTime() + { + return add ? t1.evalTime() + t2.evalTime() : t1.evalTime() - t2.evalTime(); + } + + public void setParentElement(AnimationElement ele) + { + t1.setParentElement(ele); + t2.setParentElement(ele); + } +} Index: core/src/com/kitfox/svg/animation/TrackBase.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/TrackBase.java 2012-06-17 23:56:57.684545050 +0200 @@ -0,0 +1,103 @@ +/* + * TrackManager.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, 11:34 PM + */ + +package com.kitfox.svg.animation; + +import java.util.*; + +import com.kitfox.svg.xml.*; +import com.kitfox.svg.*; + +/** + * A track holds the animation events for a single parameter of a single SVG + * element. It also contains the default value for the element, should the + * user want to see the 'unanimated' value. + * + * @author Mark McKay + * @author Mark McKay + */ +abstract public class TrackBase +{ + protected final String attribName; + protected final int attribType; //AnimationElement.AT_* + + /** Element we're animating */ + protected final SVGElement parent; + + //It doesn't make sense to sort this, since some events will depend on + // other events - in many cases, there will be no meaningful sorted order. + final ArrayList animEvents = new ArrayList(); + + /** Creates a new instance of TrackManager */ +// public TrackBase(SVGElement parent) +// { +// this(parent, "", AnimationElement.AT_AUTO); +// } + + /** + * Creates a track that would be valid for the name and type of element + * passed in. Does not actually add this elemnt to the track. + */ + public TrackBase(SVGElement parent, AnimationElement ele) throws SVGElementException + { + this(parent, ele.getAttribName(), ele.getAttribType()); + } + + public TrackBase(SVGElement parent, String attribName, int attribType) throws SVGElementException + { + this.parent = parent; + this.attribName = attribName; + this.attribType = attribType; + + //Make sure parent has an attribute we will write to + if (attribType == AnimationElement.AT_AUTO + && !parent.hasAttribute(attribName, AnimationElement.AT_CSS) + && !parent.hasAttribute(attribName, AnimationElement.AT_XML)) + { + parent.addAttribute(attribName, AnimationElement.AT_CSS, ""); + } + else if (!parent.hasAttribute(attribName, attribType)) + { + parent.addAttribute(attribName, attribType, ""); + } + } + + public String getAttribName() { return attribName; } + public int getAttribType() { return attribType; } + + public void addElement(AnimationElement ele) + { + animEvents.add(ele); + } + + /** + * Returns a StyleAttribute representing the value of this track at the + * passed time. If this track does not apply, returns null. + * @return - True if successful, false if a value could not be obtained + */ + abstract public boolean getValue(StyleAttribute attrib, double curTime) throws SVGException; + +} Index: core/src/com/kitfox/svg/animation/TrackColor.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/TrackColor.java 2012-06-17 23:56:57.684545050 +0200 @@ -0,0 +1,95 @@ +/* + * TrackManager.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 September 21, 2004, 11:34 PM + */ + +package com.kitfox.svg.animation; + +import com.kitfox.svg.xml.StyleAttribute; +import java.awt.*; +import java.util.*; + +import com.kitfox.svg.*; +import com.kitfox.svg.xml.*; + +/** + * A track holds the animation events for a single parameter of a single SVG + * element. It also contains the default value for the element, should the + * user want to see the 'unanimated' value. + * + * @author Mark McKay + * @author Mark McKay + */ +public class TrackColor extends TrackBase +{ + + public TrackColor(AnimationElement ele) throws SVGElementException + { + super(ele.getParent(), ele); + } + + public boolean getValue(StyleAttribute attrib, double curTime) + { + Color col = getValue(curTime); + if (col == null) return false; + + attrib.setStringValue("#" + Integer.toHexString(col.getRGB())); + return true; + } + + public Color getValue(double curTime) + { + Color retVal = null; + AnimationTimeEval state = new AnimationTimeEval(); + + for (Iterator it = animEvents.iterator(); it.hasNext();) + { + AnimateBase ele = (AnimateBase)it.next(); + AnimateColorIface eleColor = (AnimateColorIface)ele; + ele.evalParametric(state, curTime); + + //Reject value if it is in the invalid state + if (Double.isNaN(state.interp)) continue; + + if (retVal == null) + { + retVal = eleColor.evalColor(state.interp); + continue; + } + + Color curCol = eleColor.evalColor(state.interp); + switch (ele.getAdditiveType()) + { + case AnimationElement.AD_REPLACE: + retVal = curCol; + break; + case AnimationElement.AD_SUM: + retVal = new Color(curCol.getRed() + retVal.getRed(), curCol.getGreen() + retVal.getGreen(), curCol.getBlue() + retVal.getBlue()); + break; + } + } + + return retVal; + } +} Index: core/src/com/kitfox/svg/animation/TrackDouble.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/TrackDouble.java 2012-06-17 23:56:57.684545050 +0200 @@ -0,0 +1,119 @@ +/* + * TrackManager.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, 11:34 PM + */ + +package com.kitfox.svg.animation; + +import com.kitfox.svg.xml.StyleAttribute; +import java.util.*; + +import com.kitfox.svg.*; +import com.kitfox.svg.xml.*; + +/** + * A track holds the animation events for a single parameter of a single SVG + * element. It also contains the default value for the element, should the + * user want to see the 'unanimated' value. + * + * @author Mark McKay + * @author Mark McKay + */ +public class TrackDouble extends TrackBase +{ + public TrackDouble(AnimationElement ele) throws SVGElementException + { + super(ele.getParent(), ele); + } + + public boolean getValue(StyleAttribute attrib, double curTime) + { + double val = getValue(curTime); + if (Double.isNaN(val)) return false; + + attrib.setStringValue("" + val); + return true; + } + + public double getValue(double curTime) + { + double retVal = Double.NaN; + + StyleAttribute attr = null; + switch (attribType) + { + case AnimationElement.AT_CSS: + attr = parent.getStyleAbsolute(attribName); + retVal = attr.getDoubleValue(); + break; + case AnimationElement.AT_XML: + attr = parent.getPresAbsolute(attribName); + retVal = attr.getDoubleValue(); + break; + case AnimationElement.AT_AUTO: + attr = parent.getStyleAbsolute(attribName); + if (attr == null) attr = parent.getPresAbsolute(attribName); + retVal = attr.getDoubleValue(); + break; + } + + + + AnimationTimeEval state = new AnimationTimeEval(); +// boolean pastEnd = true; + + for (Iterator it = animEvents.iterator(); it.hasNext();) + { + Animate ele = (Animate)it.next(); + ele.evalParametric(state, curTime); + + //Go to next element if this one does not affect processing + if (Double.isNaN(state.interp)) continue; + + switch (ele.getAdditiveType()) + { + case AnimationElement.AD_SUM: + retVal += ele.eval(state.interp); + break; + case AnimationElement.AD_REPLACE: + retVal = ele.eval(state.interp); + break; + } + + //Evalutae accumulation if applicable + if (state.rep > 0) + { + switch (ele.getAccumulateType()) + { + case AnimationElement.AC_SUM: + retVal += ele.repeatSkipSize(state.rep); + break; + } + + } + } + + return retVal; + } +} Index: core/src/com/kitfox/svg/animation/TrackManager.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/TrackManager.java 2012-06-17 23:56:57.684545050 +0200 @@ -0,0 +1,153 @@ +/* + * TrackManager.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, 11:34 PM + */ + +package com.kitfox.svg.animation; + +import java.util.*; + +import com.kitfox.svg.*; +import java.io.Serializable; + +/** + * Every element contains tracks, which manage the animation. There is one track + * for every parameter with animation, and each track in turn is composed of + * many events. + * + * @author Mark McKay + * @author Mark McKay + */ +public class TrackManager implements Serializable +{ + public static final long serialVersionUID = 0; + + static class TrackKey + { + String name; + int type; + + TrackKey(AnimationElement base) + { + this(base.getAttribName(), base.getAttribType()); + } + + TrackKey(String name, int type) + { + this.name = name; + this.type = type; + } + + public int hashCode() { return name.hashCode() ^ type; } + public boolean equals(Object obj) + { + if (!(obj instanceof TrackKey)) return false; + TrackKey key = (TrackKey)obj; + return key.type == type && key.name.equals(name); + } + } + + HashMap tracks = new HashMap(); + + /** Creates a new instance of TrackManager */ + public TrackManager() + { + } + + /** + * Adds a new animation element to this track + */ + public void addTrackElement(AnimationElement element) throws SVGElementException + { + TrackKey key = new TrackKey(element); + + TrackBase track = (TrackBase)tracks.get(key); + + if (track == null) + { + //Create a track for this element + if (element instanceof Animate) + { + switch (((Animate)element).getDataType()) + { + case Animate.DT_REAL: + track = new TrackDouble(element); + break; + case Animate.DT_COLOR: + track = new TrackColor(element); + break; + case Animate.DT_PATH: + track = new TrackPath(element); + break; + default: + throw new RuntimeException(""); + } + } + else if (element instanceof AnimateColor) + { + track = new TrackColor(element); + } + else if (element instanceof AnimateTransform || element instanceof AnimateMotion) + { + track = new TrackTransform(element); + } + + tracks.put(key, track); + } + + track.addElement(element); + } + + public TrackBase getTrack(String name, int type) + { + //Handle AUTO, which will match either CSS or XML (in that order) + if (type == AnimationElement.AT_AUTO) + { + TrackBase t = getTrack(name, AnimationElement.AT_CSS); + if (t != null) return t; + t = getTrack(name, AnimationElement.AT_XML); + if (t != null) return t; + return null; + } + + //Get requested attribute + TrackKey key = new TrackKey(name, type); + TrackBase t = (TrackBase)tracks.get(key); + if (t != null) return t; + + //If that didn't exist, see if one exists of type AUTO + key = new TrackKey(name, AnimationElement.AT_AUTO); + return (TrackBase)tracks.get(key); + } + + public int getNumTracks() + { + return tracks.size(); + } + + public Iterator iterator() + { + return tracks.values().iterator(); + } +} Index: core/src/com/kitfox/svg/animation/TrackMotion.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/TrackMotion.java 2012-06-17 23:56:57.684545050 +0200 @@ -0,0 +1,128 @@ +/* + * TrackManager.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 September 21, 2004, 11:34 PM + */ + +package com.kitfox.svg.animation; + +import com.kitfox.svg.xml.StyleAttribute; +import java.awt.geom.*; +import java.util.*; + +import com.kitfox.svg.*; +import com.kitfox.svg.xml.*; + +/** + * A track holds the animation events for a single parameter of a single SVG + * element. It also contains the default value for the element, should the + * user want to see the 'unanimated' value. + * + * @author Mark McKay + * @author Mark McKay + */ +public class TrackMotion extends TrackBase +{ + public TrackMotion(AnimationElement ele) throws SVGElementException + { + //The motion element implies a CSS attribute of transform +// super(ele.getParent(), "transform", AnimationElement.AT_CSS); + super(ele.getParent(), ele); + } + + public boolean getValue(StyleAttribute attrib, double curTime) throws SVGException + { + AffineTransform retVal = new AffineTransform(); + retVal = getValue(retVal, curTime); +// AffineTransform val = getValue(curTime); +// if (val == null) return false; + + double[] mat = new double[6]; + retVal.getMatrix(mat); + attrib.setStringValue("matrix(" + mat[0] + " " + mat[1] + " " + mat[2] + " " + mat[3] + " " + mat[4] + " " + mat[5] + ")"); + return true; + } + + public AffineTransform getValue(AffineTransform retVal, double curTime) throws SVGException + { + //Init transform with default state + StyleAttribute attr = null; + switch (attribType) + { + case AnimationElement.AT_CSS: + attr = parent.getStyleAbsolute(attribName); + retVal.setTransform(SVGElement.parseSingleTransform(attr.getStringValue())); + break; + case AnimationElement.AT_XML: + attr = parent.getPresAbsolute(attribName); + retVal.setTransform(SVGElement.parseSingleTransform(attr.getStringValue())); + break; + case AnimationElement.AT_AUTO: + attr = parent.getStyleAbsolute(attribName); + if (attr == null) attr = parent.getPresAbsolute(attribName); + retVal.setTransform(SVGElement.parseSingleTransform(attr.getStringValue())); + break; + } + + + //Update transform with time based information + AnimationTimeEval state = new AnimationTimeEval(); + AffineTransform xform = new AffineTransform(); +// boolean pastEnd = true; + + for (Iterator it = animEvents.iterator(); it.hasNext();) + { + AnimateMotion ele = (AnimateMotion)it.next(); + ele.evalParametric(state, curTime); + + //Go to next element if this one does not affect processing + if (Double.isNaN(state.interp)) continue; + + switch (ele.getAdditiveType()) + { + case AnimationElement.AD_SUM: + retVal.concatenate(ele.eval(xform, state.interp)); + break; + case AnimationElement.AD_REPLACE: + retVal.setTransform(ele.eval(xform, state.interp)); + break; + } + + //Evaluate accumulation if applicable +/* + if (state.rep > 0) + { + switch (ele.getAccumulateType()) + { + case AnimationElement.AC_SUM: + retVal += ele.repeatSkipSize(state.rep); + break; + } + + } +*/ + } + + return retVal; + } +} Index: core/src/com/kitfox/svg/animation/TrackPath.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/TrackPath.java 2012-06-17 23:56:57.684545050 +0200 @@ -0,0 +1,100 @@ +/* + * TrackManager.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 September 21, 2004, 11:34 PM + */ + +package com.kitfox.svg.animation; + +import com.kitfox.svg.xml.StyleAttribute; +import java.awt.*; +import java.awt.geom.*; +import java.util.*; + +import com.kitfox.svg.pathcmd.*; +import com.kitfox.svg.*; +import com.kitfox.svg.xml.*; + +/** + * A track holds the animation events for a single parameter of a single SVG + * element. It also contains the default value for the element, should the + * user want to see the 'unanimated' value. + * + * @author Mark McKay + * @author Mark McKay + */ +public class TrackPath extends TrackBase +{ + + public TrackPath(AnimationElement ele) throws SVGElementException + { + super(ele.getParent(), ele); + } + + public boolean getValue(StyleAttribute attrib, double curTime) + { + GeneralPath path = getValue(curTime); + if (path == null) return false; + + attrib.setStringValue(PathUtil.buildPathString(path)); + return true; + } + + public GeneralPath getValue(double curTime) + { + GeneralPath retVal = null; + AnimationTimeEval state = new AnimationTimeEval(); + + for (Iterator it = animEvents.iterator(); it.hasNext();) + { + AnimateBase ele = (AnimateBase)it.next(); + Animate eleAnim = (Animate)ele; + ele.evalParametric(state, curTime); + + //Reject value if it is in the invalid state + if (Double.isNaN(state.interp)) continue; + + if (retVal == null) + { + retVal = eleAnim.evalPath(state.interp); + continue; + } + + GeneralPath curPath = eleAnim.evalPath(state.interp); + switch (ele.getAdditiveType()) + { + case AnimationElement.AD_REPLACE: + retVal = curPath; + break; + case AnimationElement.AD_SUM: + throw new RuntimeException("Not implemented"); +// retVal = new Color(curCol.getRed() + retVal.getRed(), curCol.getGreen() + retVal.getGreen(), curCol.getBlue() + retVal.getBlue()); +// break; + default: + throw new RuntimeException(); + } + } + + return retVal; + } +} Index: core/src/com/kitfox/svg/animation/TrackTransform.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/animation/TrackTransform.java 2012-06-17 23:56:57.684545050 +0200 @@ -0,0 +1,112 @@ +/* + * TrackManager.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 September 21, 2004, 11:34 PM + */ + +package com.kitfox.svg.animation; + +import com.kitfox.svg.xml.StyleAttribute; +import java.awt.geom.*; +import java.util.*; + +import com.kitfox.svg.*; +import com.kitfox.svg.xml.*; + +/** + * A track holds the animation events for a single parameter of a single SVG + * element. It also contains the default value for the element, should the + * user want to see the 'unanimated' value. + * + * @author Mark McKay + * @author Mark McKay + */ +public class TrackTransform extends TrackBase +{ + public TrackTransform(AnimationElement ele) throws SVGElementException + { + super(ele.getParent(), ele); + } + + public boolean getValue(StyleAttribute attrib, double curTime) throws SVGException + { + AffineTransform retVal = new AffineTransform(); + retVal = getValue(retVal, curTime); +// AffineTransform val = getValue(curTime); +// if (val == null) return false; + + double[] mat = new double[6]; + retVal.getMatrix(mat); + attrib.setStringValue("matrix(" + mat[0] + " " + mat[1] + " " + mat[2] + " " + mat[3] + " " + mat[4] + " " + mat[5] + ")"); + return true; + } + + public AffineTransform getValue(AffineTransform retVal, double curTime) throws SVGException + { + //Init transform with default state + StyleAttribute attr = null; + switch (attribType) + { + case AnimationElement.AT_CSS: + attr = parent.getStyleAbsolute(attribName); + retVal.setTransform(SVGElement.parseSingleTransform(attr.getStringValue())); + break; + case AnimationElement.AT_XML: + attr = parent.getPresAbsolute(attribName); + retVal.setTransform(SVGElement.parseSingleTransform(attr.getStringValue())); + break; + case AnimationElement.AT_AUTO: + attr = parent.getStyleAbsolute(attribName); + if (attr == null) attr = parent.getPresAbsolute(attribName); + retVal.setTransform(SVGElement.parseSingleTransform(attr.getStringValue())); + break; + } + + + //Update transform with time based information + AnimationTimeEval state = new AnimationTimeEval(); + AffineTransform xform = new AffineTransform(); + + for (Iterator it = animEvents.iterator(); it.hasNext();) + { + AnimateXform ele = (AnimateXform)it.next(); + ele.evalParametric(state, curTime); + + //Go to next element if this one does not affect processing + if (Double.isNaN(state.interp)) continue; + + switch (ele.getAdditiveType()) + { + case AnimationElement.AD_SUM: + retVal.concatenate(ele.eval(xform, state.interp)); + break; + case AnimationElement.AD_REPLACE: + retVal.setTransform(ele.eval(xform, state.interp)); + break; + } + + } + + return retVal; + } +} Index: core/src/com/kitfox/svg/SVGElement.java =================================================================== --- core.orig/src/com/kitfox/svg/SVGElement.java 2012-05-11 17:03:52.404311564 +0200 +++ core/src/com/kitfox/svg/SVGElement.java 2012-06-17 23:56:57.732545052 +0200 @@ -33,6 +33,7 @@ import java.awt.geom.*; import org.xml.sax.*; +import com.kitfox.svg.animation.*; import com.kitfox.svg.pathcmd.*; import com.kitfox.svg.xml.*; import java.io.Serializable; @@ -100,6 +101,8 @@ */ // protected SVGUniverse universe; + protected final TrackManager trackManager = new TrackManager(); + boolean dirty = true; // public static final Matcher adobeId = Pattern.compile("(.*)_1_").matcher(""); @@ -265,6 +268,46 @@ } } + public void addAttribute(String name, int attribType, String value) throws SVGElementException + { + if (hasAttribute(name, attribType)) throw new SVGElementException(this, "Attribute " + name + "(" + AnimationElement.animationElementToString(attribType) + ") already exists"); + + //Alter layout for id attribute + if ("id".equals(name) && diagram != null) + { + diagram.removeElement(this.id); + this.id = name; + diagram.setElement(this.id, this); + } + + switch (attribType) + { + case AnimationElement.AT_CSS: + inlineStyles.put(name, new StyleAttribute(name, value)); + return; + case AnimationElement.AT_XML: + presAttribs.put(name, new StyleAttribute(name, value)); + return; + } + + throw new SVGElementException(this, "Invalid attribute type " + attribType); + } + + public boolean hasAttribute(String name, int attribType) throws SVGElementException + { + switch (attribType) + { + case AnimationElement.AT_CSS: + return inlineStyles.containsKey(name); + case AnimationElement.AT_XML: + return presAttribs.containsKey(name); + case AnimationElement.AT_AUTO: + return inlineStyles.containsKey(name) || presAttribs.containsKey(name); + } + + throw new SVGElementException(this, "Invalid attribute type " + attribType); + } + /** * @return a set of Strings that corespond to CSS attributes on this element */ @@ -290,6 +333,12 @@ children.add(child); child.parent = this; child.setDiagram(diagram); + + //Add info to track if we've scanned animation element + if (child instanceof AnimationElement) + { + trackManager.addTrackElement((AnimationElement)child); + } } private void setDiagram(SVGDiagram diagram) @@ -408,6 +457,54 @@ return getStyle(attrib, true); } + + public void setAttribute(String name, int attribType, String value) throws SVGElementException + { + StyleAttribute styAttr; + + + switch (attribType) + { + case AnimationElement.AT_CSS: + { + styAttr = (StyleAttribute)inlineStyles.get(name); + break; + } + case AnimationElement.AT_XML: + { + styAttr = (StyleAttribute)presAttribs.get(name); + break; + } + case AnimationElement.AT_AUTO: + { + styAttr = (StyleAttribute)inlineStyles.get(name); + + if (styAttr == null) + { + styAttr = (StyleAttribute)presAttribs.get(name); + } + break; + } + default: + throw new SVGElementException(this, "Invalid attribute type " + attribType); + } + + if (styAttr == null) + { + throw new SVGElementException(this, "Could not find attribute " + name + "(" + AnimationElement.animationElementToString(attribType) + "). Make sure to create attribute before setting it."); + } + + //Alter layout for relevant attributes + if ("id".equals(styAttr.getName())) + { + diagram.removeElement(this.id); + this.id = name; + diagram.setElement(this.id, this); + } + + styAttr.setStringValue(value); + } + /** * Copies the current style into the passed style attribute. Checks for * inline styles first, then internal and extranal style sheets, and @@ -427,6 +524,14 @@ attrib.setStringValue(styAttr == null ? "" : styAttr.getStringValue()); + //Evalutate coresponding track, if one exists + TrackBase track = trackManager.getTrack(styName, AnimationElement.AT_CSS); + if (track != null) + { + track.getValue(attrib, diagram.getUniverse().getCurTime()); + return true; + } + //Return if we've found a non animated style if (styAttr != null) return true; @@ -439,6 +544,14 @@ attrib.setStringValue(presAttr == null ? "" : presAttr.getStringValue()); + //Evalutate coresponding track, if one exists + track = trackManager.getTrack(styName, AnimationElement.AT_XML); + if (track != null) + { + track.getValue(attrib, diagram.getUniverse().getCurTime()); + return true; + } + //Return if we've found a presentation attribute instead if (presAttr != null) return true; @@ -480,6 +593,14 @@ //Copy presentation value directly attrib.setStringValue(presAttr == null ? "" : presAttr.getStringValue()); + //Evalutate coresponding track, if one exists + TrackBase track = trackManager.getTrack(presName, AnimationElement.AT_XML); + if (track != null) + { + track.getValue(attrib, diagram.getUniverse().getCurTime()); + return true; + } + //Return if we found presentation attribute if (presAttr != null) return true; Index: core/src/com/kitfox/svg/SVGLoader.java =================================================================== --- core.orig/src/com/kitfox/svg/SVGLoader.java 2012-05-11 17:03:52.404311564 +0200 +++ core/src/com/kitfox/svg/SVGLoader.java 2012-06-17 23:56:57.732545052 +0200 @@ -33,6 +33,8 @@ import org.xml.sax.*; import org.xml.sax.helpers.DefaultHandler; +import com.kitfox.svg.animation.*; + /** * @author Mark McKay * @author Mark McKay @@ -75,6 +77,10 @@ //Compile a list of important builder classes nodeClasses.put("a", A.class); + nodeClasses.put("animate", Animate.class); + nodeClasses.put("animatecolor", AnimateColor.class); + nodeClasses.put("animatemotion", AnimateMotion.class); + nodeClasses.put("animatetransform", AnimateTransform.class); nodeClasses.put("circle", Circle.class); nodeClasses.put("clippath", ClipPath.class); nodeClasses.put("defs", Defs.class); @@ -98,6 +104,7 @@ nodeClasses.put("polyline", Polyline.class); nodeClasses.put("radialgradient", RadialGradient.class); nodeClasses.put("rect", Rect.class); + nodeClasses.put("set", SetSmil.class); nodeClasses.put("shape", ShapeElement.class); nodeClasses.put("stop", Stop.class); nodeClasses.put("style", Style.class); Index: core/src/com/kitfox/svg/SVGLoaderHelper.java =================================================================== --- core.orig/src/com/kitfox/svg/SVGLoaderHelper.java 2012-05-11 17:03:52.404311564 +0200 +++ core/src/com/kitfox/svg/SVGLoaderHelper.java 2012-06-17 23:56:57.740545051 +0200 @@ -28,6 +28,9 @@ package com.kitfox.svg; import java.net.*; +import java.io.*; + +import com.kitfox.svg.animation.parser.*; /** * @author Mark McKay @@ -47,6 +50,11 @@ public final URI xmlBase; + /** + * Animate nodes use this to parse their time strings + */ + public final AnimTimeParser animTimeParser = new AnimTimeParser(new StringReader("")); + /** Creates a new instance of SVGLoaderHelper */ public SVGLoaderHelper(URI xmlBase, SVGUniverse universe, SVGDiagram diagram) { Index: core/src/com/kitfox/svg/app/MainFrame.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/app/MainFrame.java 2012-06-17 23:56:57.748545052 +0200 @@ -0,0 +1,134 @@ +/* + * MainFrame.java + * + * Created on September 6, 2004, 1:19 AM + */ + +package com.kitfox.svg.app; + +/** + * + * @author kitfox + */ +public class MainFrame extends javax.swing.JFrame +{ + public static final long serialVersionUID = 1; + + /** Creates new form MainFrame */ + public MainFrame() + { + initComponents(); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + private void initComponents()//GEN-BEGIN:initComponents + { + jPanel1 = new javax.swing.JPanel(); + bn_svgViewer = new javax.swing.JButton(); + bn_svgViewer1 = new javax.swing.JButton(); + jPanel2 = new javax.swing.JPanel(); + bn_quit = new javax.swing.JButton(); + + setTitle("SVG Salamander - Application Launcher"); + addWindowListener(new java.awt.event.WindowAdapter() + { + public void windowClosing(java.awt.event.WindowEvent evt) + { + exitForm(evt); + } + }); + + jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.Y_AXIS)); + + bn_svgViewer.setText("SVG Viewer (No animation)"); + bn_svgViewer.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + bn_svgViewerActionPerformed(evt); + } + }); + + jPanel1.add(bn_svgViewer); + + bn_svgViewer1.setText("SVG Player (Animation)"); + bn_svgViewer1.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + bn_svgViewer1ActionPerformed(evt); + } + }); + + jPanel1.add(bn_svgViewer1); + + getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER); + + bn_quit.setText("Quit"); + bn_quit.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + bn_quitActionPerformed(evt); + } + }); + + jPanel2.add(bn_quit); + + getContentPane().add(jPanel2, java.awt.BorderLayout.SOUTH); + + pack(); + }//GEN-END:initComponents + + private void bn_svgViewer1ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_svgViewer1ActionPerformed + {//GEN-HEADEREND:event_bn_svgViewer1ActionPerformed + SVGPlayer.main(null); + + close(); + }//GEN-LAST:event_bn_svgViewer1ActionPerformed + + private void bn_svgViewerActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_svgViewerActionPerformed + {//GEN-HEADEREND:event_bn_svgViewerActionPerformed + SVGViewer.main(null); + + close(); + }//GEN-LAST:event_bn_svgViewerActionPerformed + + private void bn_quitActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_quitActionPerformed + {//GEN-HEADEREND:event_bn_quitActionPerformed + exitForm(null); + }//GEN-LAST:event_bn_quitActionPerformed + + /** Exit the Application */ + private void exitForm(java.awt.event.WindowEvent evt)//GEN-FIRST:event_exitForm + { + System.exit(0); + }//GEN-LAST:event_exitForm + + private void close() + { + this.setVisible(false); + this.dispose(); + } + + /** + * @param args the command line arguments + */ + public static void main(String args[]) + { + new MainFrame().setVisible(true); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton bn_quit; + private javax.swing.JButton bn_svgViewer; + private javax.swing.JButton bn_svgViewer1; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + // End of variables declaration//GEN-END:variables + +} Index: core/src/com/kitfox/svg/app/PlayerDialog.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/app/PlayerDialog.java 2012-06-17 23:56:57.748545052 +0200 @@ -0,0 +1,289 @@ +/* + * PlayerDialog.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 September 28, 2004, 9:56 PM + */ + +package com.kitfox.svg.app; + +/** + * + * @author kitfox + */ +public class PlayerDialog extends javax.swing.JDialog implements PlayerThreadListener +{ + public static final long serialVersionUID = 1; + + PlayerThread thread; + + final SVGPlayer parent; + + /** Creates new form PlayerDialog */ + public PlayerDialog(SVGPlayer parent) + { + super(parent, false); + initComponents(); + + this.parent = parent; + + thread = new PlayerThread(); + thread.addListener(this); + + text_timeStepActionPerformed(null); + } + + public void updateTime(double curTime, double timeStep, int playState) + { + if (playState == PlayerThread.PS_STOP) return; + + text_curTime.setText("" + (float)curTime); + parent.updateTime(curTime); +// text_timeStep.setText("" + (int)(1.0 / timeStep)); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() + { + jPanel1 = new javax.swing.JPanel(); + bn_playBack = new javax.swing.JButton(); + bn_stop = new javax.swing.JButton(); + bn_playFwd = new javax.swing.JButton(); + jPanel2 = new javax.swing.JPanel(); + jPanel3 = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + text_curTime = new javax.swing.JTextField(); + bn_time0 = new javax.swing.JButton(); + jPanel4 = new javax.swing.JPanel(); + jLabel2 = new javax.swing.JLabel(); + text_timeStep = new javax.swing.JTextField(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + setTitle("Player"); + addWindowListener(new java.awt.event.WindowAdapter() + { + public void windowClosed(java.awt.event.WindowEvent evt) + { + formWindowClosed(evt); + } + }); + + bn_playBack.setText("<"); + bn_playBack.setToolTipText("Play backwards"); + bn_playBack.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + bn_playBackActionPerformed(evt); + } + }); + + jPanel1.add(bn_playBack); + + bn_stop.setText("||"); + bn_stop.setToolTipText("Stop playback"); + bn_stop.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + bn_stopActionPerformed(evt); + } + }); + + jPanel1.add(bn_stop); + + bn_playFwd.setText(">"); + bn_playFwd.setToolTipText("Play Forwards"); + bn_playFwd.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + bn_playFwdActionPerformed(evt); + } + }); + + jPanel1.add(bn_playFwd); + + getContentPane().add(jPanel1, java.awt.BorderLayout.NORTH); + + jPanel2.setLayout(new javax.swing.BoxLayout(jPanel2, javax.swing.BoxLayout.Y_AXIS)); + + jLabel1.setText("Cur Time"); + jPanel3.add(jLabel1); + + text_curTime.setHorizontalAlignment(javax.swing.JTextField.LEFT); + text_curTime.setText("0"); + text_curTime.setPreferredSize(new java.awt.Dimension(100, 21)); + text_curTime.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + text_curTimeActionPerformed(evt); + } + }); + text_curTime.addFocusListener(new java.awt.event.FocusAdapter() + { + public void focusLost(java.awt.event.FocusEvent evt) + { + text_curTimeFocusLost(evt); + } + }); + + jPanel3.add(text_curTime); + + bn_time0.setText("Time 0"); + bn_time0.setToolTipText("Reset time to first frame"); + bn_time0.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + bn_time0ActionPerformed(evt); + } + }); + + jPanel3.add(bn_time0); + + jPanel2.add(jPanel3); + + jLabel2.setText("Frames Per Second"); + jPanel4.add(jLabel2); + + text_timeStep.setHorizontalAlignment(javax.swing.JTextField.RIGHT); + text_timeStep.setText("60"); + text_timeStep.setPreferredSize(new java.awt.Dimension(100, 21)); + text_timeStep.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + text_timeStepActionPerformed(evt); + } + }); + text_timeStep.addFocusListener(new java.awt.event.FocusAdapter() + { + public void focusLost(java.awt.event.FocusEvent evt) + { + text_timeStepFocusLost(evt); + } + }); + + jPanel4.add(text_timeStep); + + jPanel2.add(jPanel4); + + getContentPane().add(jPanel2, java.awt.BorderLayout.CENTER); + + pack(); + }// //GEN-END:initComponents + + private void bn_time0ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_time0ActionPerformed + {//GEN-HEADEREND:event_bn_time0ActionPerformed + thread.setCurTime(0); + }//GEN-LAST:event_bn_time0ActionPerformed + + private void bn_playFwdActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_playFwdActionPerformed + {//GEN-HEADEREND:event_bn_playFwdActionPerformed + thread.setPlayState(PlayerThread.PS_PLAY_FWD); + }//GEN-LAST:event_bn_playFwdActionPerformed + + private void bn_stopActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_stopActionPerformed + {//GEN-HEADEREND:event_bn_stopActionPerformed + thread.setPlayState(PlayerThread.PS_STOP); + }//GEN-LAST:event_bn_stopActionPerformed + + private void bn_playBackActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_playBackActionPerformed + {//GEN-HEADEREND:event_bn_playBackActionPerformed + thread.setPlayState(PlayerThread.PS_PLAY_BACK); + }//GEN-LAST:event_bn_playBackActionPerformed + + private void formWindowClosed(java.awt.event.WindowEvent evt)//GEN-FIRST:event_formWindowClosed + {//GEN-HEADEREND:event_formWindowClosed +// thread.exit(); + }//GEN-LAST:event_formWindowClosed + + private void text_timeStepFocusLost(java.awt.event.FocusEvent evt)//GEN-FIRST:event_text_timeStepFocusLost + {//GEN-HEADEREND:event_text_timeStepFocusLost + text_timeStepActionPerformed(null); + }//GEN-LAST:event_text_timeStepFocusLost + + private void text_timeStepActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_text_timeStepActionPerformed + {//GEN-HEADEREND:event_text_timeStepActionPerformed + try + { + int val = Integer.parseInt(text_timeStep.getText()); + thread.setTimeStep(1.0 / val); + } + catch (Exception e) + { + } + + double d = thread.getTimeStep(); + String newStrn = "" + (int)(1f / d); + if (newStrn.equals(text_timeStep.getText())) return; + text_timeStep.setText(newStrn); + +// text_timeStepActionPerformed(null); + }//GEN-LAST:event_text_timeStepActionPerformed + + private void text_curTimeActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_text_curTimeActionPerformed + {//GEN-HEADEREND:event_text_curTimeActionPerformed + try + { + double val = Double.parseDouble(text_curTime.getText()); + thread.setCurTime(val); + } + catch (Exception e) + { + } + + double d = thread.getCurTime(); + text_curTime.setText("" + (float)d); + + text_timeStepActionPerformed(null); + }//GEN-LAST:event_text_curTimeActionPerformed + + private void text_curTimeFocusLost(java.awt.event.FocusEvent evt)//GEN-FIRST:event_text_curTimeFocusLost + {//GEN-HEADEREND:event_text_curTimeFocusLost + text_curTimeActionPerformed(null); + }//GEN-LAST:event_text_curTimeFocusLost + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton bn_playBack; + private javax.swing.JButton bn_playFwd; + private javax.swing.JButton bn_stop; + private javax.swing.JButton bn_time0; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel3; + private javax.swing.JPanel jPanel4; + private javax.swing.JTextField text_curTime; + private javax.swing.JTextField text_timeStep; + // End of variables declaration//GEN-END:variables + +} Index: core/src/com/kitfox/svg/app/PlayerThread.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/app/PlayerThread.java 2012-06-17 23:56:57.748545052 +0200 @@ -0,0 +1,129 @@ +/* + * PlayerThread.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 September 28, 2004, 10:07 PM + */ + + +package com.kitfox.svg.app; + +import java.util.*; + +/** + * + * @author kitfox + */ +public class PlayerThread implements Runnable +{ + HashSet listeners = new HashSet(); + + double curTime = 0; + double timeStep = .2; + + public static final int PS_STOP = 0; + public static final int PS_PLAY_FWD = 1; + public static final int PS_PLAY_BACK = 2; + + int playState = PS_STOP; + + Thread thread; + + /** Creates a new instance of PlayerThread */ + public PlayerThread() + { + thread = new Thread(this); + thread.start(); + } + + public void run() + { + while (thread != null) + { + synchronized (this) + { + switch (playState) + { + case PS_PLAY_FWD: + curTime += timeStep; + break; + case PS_PLAY_BACK: + curTime -= timeStep; + if (curTime < 0) curTime = 0; + break; + default: + case PS_STOP: + break; + } + + fireTimeUpdateEvent(); + } + + try + { + Thread.sleep((long)(timeStep * 1000)); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + } + + public void exit() { thread = null; } + public synchronized void addListener(PlayerThreadListener listener) + { + listeners.add(listener); + } + + public synchronized double getCurTime() { return curTime; } + + public synchronized void setCurTime(double time) + { + curTime = time; + } + + public synchronized double getTimeStep() { return timeStep; } + + public synchronized void setTimeStep(double time) + { + timeStep = time; + if (timeStep < .01) timeStep = .01; + } + + public synchronized int getPlayState() { return playState; } + + public synchronized void setPlayState(int playState) + { + this.playState = playState; + } + + private void fireTimeUpdateEvent() + { + for (Iterator it = listeners.iterator(); it.hasNext();) + { + PlayerThreadListener listener = (PlayerThreadListener)it.next(); + listener.updateTime(curTime, timeStep, playState); + } + } +} Index: core/src/com/kitfox/svg/app/PlayerThreadListener.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/app/PlayerThreadListener.java 2012-06-17 23:56:57.748545052 +0200 @@ -0,0 +1,37 @@ +/* + * PlayerThreadListener.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 September 28, 2004, 10:15 PM + */ + +package com.kitfox.svg.app; + +/** + * + * @author kitfox + */ +public interface PlayerThreadListener +{ + public void updateTime(double curTime, double timeStep, int playState); +} Index: core/src/com/kitfox/svg/app/SVGPlayer.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/app/SVGPlayer.java 2012-06-17 23:56:57.748545052 +0200 @@ -0,0 +1,436 @@ +/* + * SVGViewer.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 April 3, 2004, 5:28 PM + */ + +package com.kitfox.svg.app; + + +import com.kitfox.svg.SVGDiagram; +import com.kitfox.svg.SVGDisplayPanel; +import com.kitfox.svg.SVGElement; +import com.kitfox.svg.SVGException; +import com.kitfox.svg.SVGUniverse; +import java.awt.Color; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.Point2D; +import java.io.File; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.net.URLEncoder; +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; + +/** + * @author Mark McKay + * @author Mark McKay + */ +public class SVGPlayer extends javax.swing.JFrame +{ + public static final long serialVersionUID = 1; + + SVGDisplayPanel svgDisplayPanel = new SVGDisplayPanel(); + + final PlayerDialog playerDialog; + + SVGUniverse universe; + + /** FileChooser for running in trusted environments */ + final JFileChooser fileChooser; + { +// fileChooser = new JFileChooser(new File(".")); + JFileChooser fc = null; + try + { + fc = new JFileChooser(); + fc.setFileFilter( + new javax.swing.filechooser.FileFilter() { + final Matcher matchLevelFile = Pattern.compile(".*\\.svg[z]?").matcher(""); + + public boolean accept(File file) + { + if (file.isDirectory()) return true; + + matchLevelFile.reset(file.getName()); + return matchLevelFile.matches(); + } + + public String getDescription() { return "SVG file (*.svg, *.svgz)"; } + } + ); + } + catch (AccessControlException ex) + { + //Do not create file chooser if webstart refuses permissions + } + fileChooser = fc; + } + + /** Backup file service for opening files in WebStart situations */ + /* + final FileOpenService fileOpenService; + { + try + { + fileOpenService = (FileOpenService)ServiceManager.lookup("javax.jnlp.FileOpenService"); + } + catch (UnavailableServiceException e) + { + fileOpenService = null; + } + } + */ + + /** Creates new form SVGViewer */ + public SVGPlayer() { + initComponents(); + + setSize(800, 600); + + svgDisplayPanel.setBgColor(Color.white); + svgDisplayPanel.addMouseListener(new MouseAdapter() + { + public void mouseClicked(MouseEvent evt) + { + SVGDiagram diagram = svgDisplayPanel.getDiagram(); + if (diagram == null) return; + + System.out.println("Picking at cursor (" + evt.getX() + ", " + evt.getY() + ")"); + try + { + List paths = diagram.pick(new Point2D.Float(evt.getX(), evt.getY()), null); + for (int i = 0; i < paths.size(); i++) + { + ArrayList path = (ArrayList)paths.get(i); + System.out.println(pathToString(path)); + } + } + catch (SVGException ex) + { + ex.printStackTrace(); + } + } + } + ); + + svgDisplayPanel.setPreferredSize(getSize()); + scrollPane_svgArea.setViewportView(svgDisplayPanel); + + playerDialog = new PlayerDialog(this); + } + + private String pathToString(List path) + { + if (path.size() == 0) return ""; + + StringBuffer sb = new StringBuffer(); + sb.append(path.get(0)); + for (int i = 1; i < path.size(); i++) + { + sb.append("/"); + sb.append(((SVGElement)path.get(i)).getId()); + } + return sb.toString(); + } + + public void updateTime(double curTime) + { + try + { + if (universe != null) + { + universe.setCurTime(curTime); + universe.updateTime(); + // svgDisplayPanel.updateTime(curTime); + repaint(); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + private void loadURL(URL url) + { + boolean verbose = cmCheck_verbose.isSelected(); + + universe = new SVGUniverse(); + universe.setVerbose(verbose); + SVGDiagram diagram = null; + + if (!CheckBoxMenuItem_anonInputStream.isSelected()) + { + //Load from a disk with a valid URL + URI uri = universe.loadSVG(url); + + if (verbose) System.err.println(uri.toString()); + + diagram = universe.getDiagram(uri); + } + else + { + //Load from a stream with no particular valid URL + try + { + InputStream is = url.openStream(); + URI uri = universe.loadSVG(is, "defaultName"); + + if (verbose) System.err.println(uri.toString()); + + diagram = universe.getDiagram(uri); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + svgDisplayPanel.setDiagram(diagram); + repaint(); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() + { + scrollPane_svgArea = new javax.swing.JScrollPane(); + jMenuBar1 = new javax.swing.JMenuBar(); + menu_file = new javax.swing.JMenu(); + cm_loadFile = new javax.swing.JMenuItem(); + cm_loadUrl = new javax.swing.JMenuItem(); + menu_window = new javax.swing.JMenu(); + cm_player = new javax.swing.JMenuItem(); + jSeparator2 = new javax.swing.JSeparator(); + cm_800x600 = new javax.swing.JMenuItem(); + CheckBoxMenuItem_anonInputStream = new javax.swing.JCheckBoxMenuItem(); + cmCheck_verbose = new javax.swing.JCheckBoxMenuItem(); + menu_help = new javax.swing.JMenu(); + cm_about = new javax.swing.JMenuItem(); + + setTitle("SVG Player - Salamander Project"); + addWindowListener(new java.awt.event.WindowAdapter() + { + public void windowClosing(java.awt.event.WindowEvent evt) + { + exitForm(evt); + } + }); + + getContentPane().add(scrollPane_svgArea, java.awt.BorderLayout.CENTER); + + menu_file.setMnemonic('f'); + menu_file.setText("File"); + cm_loadFile.setMnemonic('l'); + cm_loadFile.setText("Load File..."); + cm_loadFile.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + cm_loadFileActionPerformed(evt); + } + }); + + menu_file.add(cm_loadFile); + + cm_loadUrl.setText("Load URL..."); + cm_loadUrl.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + cm_loadUrlActionPerformed(evt); + } + }); + + menu_file.add(cm_loadUrl); + + jMenuBar1.add(menu_file); + + menu_window.setText("Window"); + cm_player.setText("Player"); + cm_player.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + cm_playerActionPerformed(evt); + } + }); + + menu_window.add(cm_player); + + menu_window.add(jSeparator2); + + cm_800x600.setText("800 x 600"); + cm_800x600.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + cm_800x600ActionPerformed(evt); + } + }); + + menu_window.add(cm_800x600); + + CheckBoxMenuItem_anonInputStream.setText("Anonymous Input Stream"); + menu_window.add(CheckBoxMenuItem_anonInputStream); + + cmCheck_verbose.setText("Verbose"); + cmCheck_verbose.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + cmCheck_verboseActionPerformed(evt); + } + }); + + menu_window.add(cmCheck_verbose); + + jMenuBar1.add(menu_window); + + menu_help.setText("Help"); + cm_about.setText("About..."); + cm_about.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + cm_aboutActionPerformed(evt); + } + }); + + menu_help.add(cm_about); + + jMenuBar1.add(menu_help); + + setJMenuBar(jMenuBar1); + + pack(); + }// //GEN-END:initComponents + + private void cm_loadUrlActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadUrlActionPerformed + {//GEN-HEADEREND:event_cm_loadUrlActionPerformed + String urlStrn = JOptionPane.showInputDialog(this, "Enter URL of SVG file"); + if (urlStrn == null) return; + + try + { + URL url = new URL(URLEncoder.encode(urlStrn, "UTF-8")); + loadURL(url); + } + catch (Exception e) + { + e.printStackTrace(); + } + + }//GEN-LAST:event_cm_loadUrlActionPerformed + + private void cmCheck_verboseActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cmCheck_verboseActionPerformed + {//GEN-HEADEREND:event_cmCheck_verboseActionPerformed +// TODO add your handling code here: + }//GEN-LAST:event_cmCheck_verboseActionPerformed + + private void cm_playerActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_playerActionPerformed + {//GEN-HEADEREND:event_cm_playerActionPerformed + playerDialog.setVisible(true); + }//GEN-LAST:event_cm_playerActionPerformed + + private void cm_aboutActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_aboutActionPerformed + {//GEN-HEADEREND:event_cm_aboutActionPerformed + VersionDialog dia = new VersionDialog(this, true, cmCheck_verbose.isSelected()); + dia.setVisible(true); +// JOptionPane.showMessageDialog(this, "Salamander SVG - Created by Mark McKay\nhttp://www.kitfox.com"); + }//GEN-LAST:event_cm_aboutActionPerformed + + private void cm_800x600ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cm_800x600ActionPerformed + setSize(800, 600); + }//GEN-LAST:event_cm_800x600ActionPerformed + + private void cm_loadFileActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadFileActionPerformed + {//GEN-HEADEREND:event_cm_loadFileActionPerformed + boolean verbose = cmCheck_verbose.isSelected(); + + try + { + int retVal = fileChooser.showOpenDialog(this); + if (retVal == JFileChooser.APPROVE_OPTION) + { + File chosenFile = fileChooser.getSelectedFile(); + + URL url = chosenFile.toURI().toURL(); + + loadURL(url); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + + }//GEN-LAST:event_cm_loadFileActionPerformed + + /** Exit the Application */ + private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm + System.exit(0); + }//GEN-LAST:event_exitForm + + /** + * @param args the command line arguments + */ + public static void main(String args[]) { + new SVGPlayer().setVisible(true); + } + + public void updateTime(double curTime, double timeStep, int playState) + { + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBoxMenuItem CheckBoxMenuItem_anonInputStream; + private javax.swing.JCheckBoxMenuItem cmCheck_verbose; + private javax.swing.JMenuItem cm_800x600; + private javax.swing.JMenuItem cm_about; + private javax.swing.JMenuItem cm_loadFile; + private javax.swing.JMenuItem cm_loadUrl; + private javax.swing.JMenuItem cm_player; + private javax.swing.JMenuBar jMenuBar1; + private javax.swing.JSeparator jSeparator2; + private javax.swing.JMenu menu_file; + private javax.swing.JMenu menu_help; + private javax.swing.JMenu menu_window; + private javax.swing.JScrollPane scrollPane_svgArea; + // End of variables declaration//GEN-END:variables + +} Index: core/src/com/kitfox/svg/app/SVGViewer.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/app/SVGViewer.java 2012-06-17 23:56:57.752545052 +0200 @@ -0,0 +1,432 @@ +/* + * SVGViewer.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 April 3, 2004, 5:28 PM + */ + +package com.kitfox.svg.app; + +import com.kitfox.svg.SVGCache; +import com.kitfox.svg.SVGDiagram; +import com.kitfox.svg.SVGDisplayPanel; +import com.kitfox.svg.SVGElement; +import com.kitfox.svg.SVGException; +import com.kitfox.svg.SVGUniverse; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Point; +import java.io.File; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.net.URLEncoder; +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; + + +/** + * @author Mark McKay + * @author Mark McKay + */ +public class SVGViewer extends javax.swing.JFrame +{ + public static final long serialVersionUID = 1; + + SVGDisplayPanel svgDisplayPanel = new SVGDisplayPanel(); + + /** FileChooser for running in trusted environments */ + final JFileChooser fileChooser; + { +// fileChooser = new JFileChooser(new File(".")); + JFileChooser fc = null; + try + { + fc = new JFileChooser(); + fc.setFileFilter( + new javax.swing.filechooser.FileFilter() { + final Matcher matchLevelFile = Pattern.compile(".*\\.svg[z]?").matcher(""); + + public boolean accept(File file) + { + if (file.isDirectory()) return true; + + matchLevelFile.reset(file.getName()); + return matchLevelFile.matches(); + } + + public String getDescription() { return "SVG file (*.svg, *.svgz)"; } + } + ); + } + catch (AccessControlException ex) + { + //Do not create file chooser if webstart refuses permissions + } + fileChooser = fc; + } + + /** Backup file service for opening files in WebStart situations */ + /* + final FileOpenService fileOpenService; + { + try + { + fileOpenService = (FileOpenService)ServiceManager.lookup("javax.jnlp.FileOpenService"); + } + catch (UnavailableServiceException e) + { + fileOpenService = null; + } + } + */ + + /** Creates new form SVGViewer */ + public SVGViewer() { + initComponents(); + + setSize(800, 600); + + svgDisplayPanel.setBgColor(Color.white); + + svgDisplayPanel.setPreferredSize(getSize()); + panel_svgArea.add(svgDisplayPanel, BorderLayout.CENTER); +// scrollPane_svgArea.setViewportView(svgDisplayPanel); + } + + private void loadURL(URL url) + { + boolean verbose = cmCheck_verbose.isSelected(); + +// SVGUniverse universe = new SVGUniverse(); + SVGUniverse universe = SVGCache.getSVGUniverse(); + SVGDiagram diagram = null; + URI uri; + + if (!CheckBoxMenuItem_anonInputStream.isSelected()) + { + //Load from a disk with a valid URL + uri = universe.loadSVG(url); + + if (verbose) System.err.println("Loading document " + uri.toString()); + + diagram = universe.getDiagram(uri); + } + else + { + //Load from a stream with no particular valid URL + try + { + InputStream is = url.openStream(); + uri = universe.loadSVG(is, "defaultName"); + + if (verbose) System.err.println("Loading document " + uri.toString()); + } + catch (Exception e) + { + e.printStackTrace(); + return; + } + } +/* +ByteArrayOutputStream bs = new ByteArrayOutputStream(); +ObjectOutputStream os = new ObjectOutputStream(bs); +os.writeObject(universe); +os.close(); + +ByteArrayInputStream bin = new ByteArrayInputStream(bs.toByteArray()); +ObjectInputStream is = new ObjectInputStream(bin); +universe = (SVGUniverse)is.readObject(); +is.close(); +*/ + + diagram = universe.getDiagram(uri); + + svgDisplayPanel.setDiagram(diagram); + repaint(); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() + { + scrollPane_svgArea = new javax.swing.JScrollPane(); + panel_svgArea = new javax.swing.JPanel(); + jMenuBar1 = new javax.swing.JMenuBar(); + menu_file = new javax.swing.JMenu(); + cm_loadFile = new javax.swing.JMenuItem(); + cm_loadUrl = new javax.swing.JMenuItem(); + menu_window = new javax.swing.JMenu(); + cm_800x600 = new javax.swing.JMenuItem(); + CheckBoxMenuItem_anonInputStream = new javax.swing.JCheckBoxMenuItem(); + cmCheck_verbose = new javax.swing.JCheckBoxMenuItem(); + menu_help = new javax.swing.JMenu(); + cm_about = new javax.swing.JMenuItem(); + + setTitle("SVG Viewer - Salamander Project"); + addWindowListener(new java.awt.event.WindowAdapter() + { + public void windowClosing(java.awt.event.WindowEvent evt) + { + exitForm(evt); + } + }); + + panel_svgArea.setLayout(new java.awt.BorderLayout()); + + panel_svgArea.addMouseListener(new java.awt.event.MouseAdapter() + { + public void mousePressed(java.awt.event.MouseEvent evt) + { + panel_svgAreaMousePressed(evt); + } + public void mouseReleased(java.awt.event.MouseEvent evt) + { + panel_svgAreaMouseReleased(evt); + } + }); + + scrollPane_svgArea.setViewportView(panel_svgArea); + + getContentPane().add(scrollPane_svgArea, java.awt.BorderLayout.CENTER); + + menu_file.setMnemonic('f'); + menu_file.setText("File"); + cm_loadFile.setMnemonic('l'); + cm_loadFile.setText("Load File..."); + cm_loadFile.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + cm_loadFileActionPerformed(evt); + } + }); + + menu_file.add(cm_loadFile); + + cm_loadUrl.setText("Load URL..."); + cm_loadUrl.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + cm_loadUrlActionPerformed(evt); + } + }); + + menu_file.add(cm_loadUrl); + + jMenuBar1.add(menu_file); + + menu_window.setText("Window"); + cm_800x600.setText("800 x 600"); + cm_800x600.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + cm_800x600ActionPerformed(evt); + } + }); + + menu_window.add(cm_800x600); + + CheckBoxMenuItem_anonInputStream.setText("Anonymous Input Stream"); + menu_window.add(CheckBoxMenuItem_anonInputStream); + + cmCheck_verbose.setText("Verbose"); + cmCheck_verbose.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + cmCheck_verboseActionPerformed(evt); + } + }); + + menu_window.add(cmCheck_verbose); + + jMenuBar1.add(menu_window); + + menu_help.setText("Help"); + cm_about.setText("About..."); + cm_about.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + cm_aboutActionPerformed(evt); + } + }); + + menu_help.add(cm_about); + + jMenuBar1.add(menu_help); + + setJMenuBar(jMenuBar1); + + pack(); + }// //GEN-END:initComponents + + private void cm_loadUrlActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadUrlActionPerformed + {//GEN-HEADEREND:event_cm_loadUrlActionPerformed + String urlStrn = JOptionPane.showInputDialog(this, "Enter URL of SVG file"); + if (urlStrn == null) return; + + try + { + URL url = new URL(URLEncoder.encode(urlStrn, "UTF-8")); + loadURL(url); + } + catch (Exception e) + { + e.printStackTrace(); + } + + }//GEN-LAST:event_cm_loadUrlActionPerformed + + private void panel_svgAreaMouseReleased(java.awt.event.MouseEvent evt)//GEN-FIRST:event_panel_svgAreaMouseReleased + {//GEN-HEADEREND:event_panel_svgAreaMouseReleased + SVGDiagram diagram = svgDisplayPanel.getDiagram(); + List pickedElements; + try + { + pickedElements = diagram.pick(new Point(evt.getX(), evt.getY()), null); + } + catch (SVGException ex) + { + ex.printStackTrace(); + return; + } + + System.out.println("Pick results:"); + for (Iterator it = pickedElements.iterator(); it.hasNext();) + { + ArrayList path = (ArrayList)it.next(); + + System.out.print(" Path: "); + + for (Iterator it2 = path.iterator(); it2.hasNext();) + { + SVGElement ele = (SVGElement)it2.next(); + + System.out.print("" + ele.getId() + "(" + ele.getClass().getName() + ") "); + } + System.out.println(); + } + }//GEN-LAST:event_panel_svgAreaMouseReleased + + private void panel_svgAreaMousePressed(java.awt.event.MouseEvent evt)//GEN-FIRST:event_panel_svgAreaMousePressed + {//GEN-HEADEREND:event_panel_svgAreaMousePressed + + }//GEN-LAST:event_panel_svgAreaMousePressed + + private void cmCheck_verboseActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cmCheck_verboseActionPerformed + {//GEN-HEADEREND:event_cmCheck_verboseActionPerformed + SVGCache.getSVGUniverse().setVerbose(cmCheck_verbose.isSelected()); + }//GEN-LAST:event_cmCheck_verboseActionPerformed + + private void cm_aboutActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_aboutActionPerformed + {//GEN-HEADEREND:event_cm_aboutActionPerformed + //JOptionPane.showMessageDialog(this, "Salamander SVG - Created by Mark McKay\nhttp://www.kitfox.com"); + VersionDialog dlg = new VersionDialog(this, true, cmCheck_verbose.isSelected()); + dlg.setVisible(true); + }//GEN-LAST:event_cm_aboutActionPerformed + + private void cm_800x600ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cm_800x600ActionPerformed + setSize(800, 600); + }//GEN-LAST:event_cm_800x600ActionPerformed + + private void cm_loadFileActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadFileActionPerformed + {//GEN-HEADEREND:event_cm_loadFileActionPerformed + try + { + int retVal = fileChooser.showOpenDialog(this); + if (retVal == JFileChooser.APPROVE_OPTION) + { + File chosenFile = fileChooser.getSelectedFile(); + + URL url = chosenFile.toURI().toURL(); + + loadURL(url); + } + } + /* + catch (IOException ioe) + { + try + { + //We may be in a WebStart app. Try again with a FileOpenService + FileContents fc = fileOpenService.openFileDialog(null, new String[]{"svg"}); + InputStream is = fc.getInputStream(); + String name = fc.getName(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + */ + catch (Exception e) + { + e.printStackTrace(); + } + + }//GEN-LAST:event_cm_loadFileActionPerformed + + /** Exit the Application */ + private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm +// setVisible(false); +// dispose(); + System.exit(0); + }//GEN-LAST:event_exitForm + + /** + * @param args the command line arguments + */ + public static void main(String args[]) { + new SVGViewer().setVisible(true); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBoxMenuItem CheckBoxMenuItem_anonInputStream; + private javax.swing.JCheckBoxMenuItem cmCheck_verbose; + private javax.swing.JMenuItem cm_800x600; + private javax.swing.JMenuItem cm_about; + private javax.swing.JMenuItem cm_loadFile; + private javax.swing.JMenuItem cm_loadUrl; + private javax.swing.JMenuBar jMenuBar1; + private javax.swing.JMenu menu_file; + private javax.swing.JMenu menu_help; + private javax.swing.JMenu menu_window; + private javax.swing.JPanel panel_svgArea; + private javax.swing.JScrollPane scrollPane_svgArea; + // End of variables declaration//GEN-END:variables + +} Index: core/src/com/kitfox/svg/app/VersionDialog.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/app/VersionDialog.java 2012-06-17 23:56:57.752545052 +0200 @@ -0,0 +1,151 @@ +/* + * VersionDialog.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 January 13, 2005, 7:23 AM + */ + +package com.kitfox.svg.app; + +import java.net.*; +import java.io.*; +import java.util.*; +import javax.swing.event.*; +import javax.swing.*; +import javax.swing.text.html.*; + + +/** + * + * @author kitfox + */ +public class VersionDialog extends javax.swing.JDialog +{ + public static final long serialVersionUID = 1; + + final boolean verbose; + + /** Creates new form VersionDialog */ + public VersionDialog(java.awt.Frame parent, boolean modal, boolean verbose) + { + super(parent, modal); + initComponents(); + + this.verbose = verbose; + + textpane_text.setContentType("text/html"); + + StringBuffer sb = new StringBuffer(); + try + { + URL url = getClass().getResource("/res/help/about/about.html"); + if (verbose) + { + System.err.println("" + getClass() + " trying to load about html " + url); + } + + BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); + while (true) + { + String line = reader.readLine(); + if (line == null) break; + sb.append(line); + } + + textpane_text.setText(sb.toString()); + } + catch (Exception e) + { + e.printStackTrace(); + } + + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() + { + jPanel1 = new javax.swing.JPanel(); + textpane_text = new javax.swing.JTextPane(); + jPanel2 = new javax.swing.JPanel(); + bn_close = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + setTitle("About SVG Salamander"); + jPanel1.setLayout(new java.awt.BorderLayout()); + + textpane_text.setEditable(false); + textpane_text.setPreferredSize(new java.awt.Dimension(400, 300)); + jPanel1.add(textpane_text, java.awt.BorderLayout.CENTER); + + getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER); + + bn_close.setText("Close"); + bn_close.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + bn_closeActionPerformed(evt); + } + }); + + jPanel2.add(bn_close); + + getContentPane().add(jPanel2, java.awt.BorderLayout.SOUTH); + + pack(); + } + // //GEN-END:initComponents + + private void bn_closeActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_closeActionPerformed + {//GEN-HEADEREND:event_bn_closeActionPerformed + setVisible(false); + dispose(); + }//GEN-LAST:event_bn_closeActionPerformed + + /** + * @param args the command line arguments + */ + public static void main(String args[]) + { + java.awt.EventQueue.invokeLater(new Runnable() + { + public void run() + { + new VersionDialog(new javax.swing.JFrame(), true, true).setVisible(true); + } + }); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton bn_close; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JTextPane textpane_text; + // End of variables declaration//GEN-END:variables + +} Index: core/src/com/kitfox/svg/app/ant/SVGToImageAntTask.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/app/ant/SVGToImageAntTask.java 2012-06-17 23:56:57.752545052 +0200 @@ -0,0 +1,251 @@ +/* + * IndexLoadObjectsAntTask.java + * + * Created on January 22, 2005, 10:30 AM + */ + +package com.kitfox.svg.app.ant; + +import java.awt.*; +import java.awt.image.*; +import java.util.*; +import java.util.regex.*; +import java.io.*; +import javax.imageio.*; + +//import com.kitfox.util.*; +//import com.kitfox.util.indexedObject.*; + +import org.apache.tools.ant.*; +import org.apache.tools.ant.types.*; + +import com.kitfox.svg.app.beans.*; +import com.kitfox.svg.*; +import com.kitfox.svg.xml.ColorTable; + +/** + *

Translates a group of SVG files into images.

+ * + *

Parameters:

+ *

+ * + * Example: + * <SVGToImage destDir="${index.java}" format="jpg" verbose="true"> + * <fileset dir="${dir1}"> + * <include name="*.svg"/> + * </fileset> + * <fileset dir="${dir2}"> + * <include name="*.svg"/> + * </fileset> + * </SVGToImage> + * + * + * + * @author kitfox + */ +public class SVGToImageAntTask extends Task +{ + private ArrayList filesets = new ArrayList(); + boolean verbose = false; + File destDir; + private String format = "png"; + Color backgroundColor = null; + int width = -1; + int height = -1; + boolean antiAlias = true; + String interpolation = "bicubic"; + boolean clipToViewBox = false; + boolean sizeToFit = true; + + /** Creates a new instance of IndexLoadObjectsAntTask */ + public SVGToImageAntTask() + { + } + + + public String getFormat() + { + return format; + } + + public void setFormat(String format) + { + this.format = format; + } + + public void setBackgroundColor(String bgColor) + { + this.backgroundColor = ColorTable.parseColor(bgColor); + } + + public void setHeight(int height) + { + this.height = height; + } + + public void setWidth(int width) + { + this.width = width; + } + + public void setAntiAlias(boolean antiAlias) + { + this.antiAlias = antiAlias; + } + + public void setInterpolation(String interpolation) + { + this.interpolation = interpolation; + } + + public void setSizeToFit(boolean sizeToFit) + { + this.sizeToFit = sizeToFit; + } + + public void setClipToViewBox(boolean clipToViewBox) + { + this.clipToViewBox = clipToViewBox; + } + + public void setVerbose(boolean verbose) + { + this.verbose = verbose; + } + + public void setDestDir(File destDir) + { + this.destDir = destDir; + } + + /** + * Adds a set of files. + */ + public void addFileset(FileSet set) + { + filesets.add(set); + } + + + + public void execute() + { + if (verbose) log("Building SVG images"); + + for (Iterator it = filesets.iterator(); it.hasNext();) + { + FileSet fs = (FileSet)it.next(); + FileScanner scanner = fs.getDirectoryScanner(getProject()); + String[] files = scanner.getIncludedFiles(); + + try + { + File basedir = scanner.getBasedir(); + + if (verbose) log("Scaning " + basedir); + + for (int i = 0; i < files.length; i++) + { +//System.out.println("File " + files[i]); +//System.out.println("BaseDir " + basedir); + translate(basedir, files[i]); + } + } + catch (Exception e) + { + throw new BuildException(e); + } + } + } + + private void translate(File baseDir, String shortName) throws BuildException + { + File source = new File(baseDir, shortName); + + if (verbose) log("Reading file: " + source); + + Matcher matchName = Pattern.compile("(.*)\\.svg", Pattern.CASE_INSENSITIVE).matcher(shortName); + if (matchName.matches()) + { + shortName = matchName.group(1); + } + shortName += "." + format; + + SVGIcon icon = new SVGIcon(); + icon.setSvgURI(source.toURI()); + icon.setAntiAlias(antiAlias); + if (interpolation.equals("nearest neighbor")) + { + icon.setInterpolation(SVGIcon.INTERP_NEAREST_NEIGHBOR); + } + else if (interpolation.equals("bilinear")) + { + icon.setInterpolation(SVGIcon.INTERP_BILINEAR); + } + else if (interpolation.equals("bicubic")) + { + icon.setInterpolation(SVGIcon.INTERP_BICUBIC); + } + + int iconWidth = width > 0 ? width : icon.getIconWidth(); + int iconHeight = height > 0 ? height : icon.getIconHeight(); + icon.setClipToViewbox(clipToViewBox); + icon.setPreferredSize(new Dimension(iconWidth, iconHeight)); + icon.setScaleToFit(sizeToFit); + BufferedImage image = new BufferedImage(iconWidth, iconHeight, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = image.createGraphics(); + + if (backgroundColor != null) + { + g.setColor(backgroundColor); + g.fillRect(0, 0, iconWidth, iconHeight); + } + + g.setClip(0, 0, iconWidth, iconHeight); +// g.fillRect(10, 10, 100, 100); + icon.paintIcon(null, g, 0, 0); + g.dispose(); + + File outFile = destDir == null ? new File(baseDir, shortName) : new File(destDir, shortName); + if (verbose) log("Writing file: " + outFile); + + try + { + ImageIO.write(image, format, outFile); + } + catch (IOException e) + { + log("Error writing image: " + e.getMessage()); + throw new BuildException(e); + } + + + SVGCache.getSVGUniverse().clear(); + } + +} Index: core/src/com/kitfox/svg/app/beans/ProportionalLayoutPanel.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/app/beans/ProportionalLayoutPanel.java 2012-06-17 23:56:57.784545052 +0200 @@ -0,0 +1,91 @@ +/* + * ProportionalLayoutPanel.java + * + * Created on May 7, 2005, 4:15 AM + */ + +package com.kitfox.svg.app.beans; + +import java.awt.*; +import java.util.*; +import javax.swing.*; + +/** + * Panel based on the null layout. Allows editing with absolute layout. When + * instanced, records layout dimensions of all subcomponents. Then, if the + * panel is ever resized, scales all children to fit new size. + * + * @author kitfox + */ +public class ProportionalLayoutPanel extends javax.swing.JPanel +{ + public static final long serialVersionUID = 1; + + //Margins to leave on sides of panel, expressed in fractions [0 1] + float topMargin; + float bottomMargin; + float leftMargin; + float rightMargin; + + /** Creates new form ProportionalLayoutPanel */ + public ProportionalLayoutPanel() + { + initComponents(); + } + + public void addNotify() + { + super.addNotify(); + + Rectangle rect = this.getBounds(); + JOptionPane.showMessageDialog(this, "" + rect); + } + + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() + { + jPanel1 = new javax.swing.JPanel(); + + setLayout(null); + + addComponentListener(new java.awt.event.ComponentAdapter() + { + public void componentResized(java.awt.event.ComponentEvent evt) + { + formComponentResized(evt); + } + public void componentShown(java.awt.event.ComponentEvent evt) + { + formComponentShown(evt); + } + }); + + add(jPanel1); + jPanel1.setBounds(80, 90, 280, 160); + + } + // //GEN-END:initComponents + + private void formComponentShown(java.awt.event.ComponentEvent evt)//GEN-FIRST:event_formComponentShown + {//GEN-HEADEREND:event_formComponentShown + JOptionPane.showMessageDialog(this, "" + getWidth() + ", " + getHeight()); + + }//GEN-LAST:event_formComponentShown + + private void formComponentResized(java.awt.event.ComponentEvent evt)//GEN-FIRST:event_formComponentResized + {//GEN-HEADEREND:event_formComponentResized +// TODO add your handling code here: + }//GEN-LAST:event_formComponentResized + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel jPanel1; + // End of variables declaration//GEN-END:variables + +} Index: core/src/com/kitfox/svg/app/beans/SVGPanel.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/app/beans/SVGPanel.java 2012-06-17 23:56:57.784545052 +0200 @@ -0,0 +1,243 @@ +/* + * SVGIcon.java + * + * Created on April 21, 2005, 10:43 AM + */ + +package com.kitfox.svg.app.beans; + +import javax.swing.*; +import java.awt.*; +import java.awt.geom.*; +import java.net.*; +import java.beans.*; + +import com.kitfox.svg.*; + +/** + * + * @author kitfox + */ +public class SVGPanel extends JPanel +{ + public static final long serialVersionUID = 1; + + + SVGUniverse svgUniverse = SVGCache.getSVGUniverse(); + + private boolean antiAlias; + +// private String svgPath; + URI svgURI; + + private boolean scaleToFit; + AffineTransform scaleXform = new AffineTransform(); + + /** Creates new form SVGIcon */ + public SVGPanel() + { + initComponents(); + } + + public int getSVGHeight() + { + if (scaleToFit) return getPreferredSize().height; + + SVGDiagram diagram = svgUniverse.getDiagram(svgURI); + if (diagram == null) return 0; + return (int)diagram.getHeight(); + } + + public int getSVGWidth() + { + if (scaleToFit) return getPreferredSize().width; + + SVGDiagram diagram = svgUniverse.getDiagram(svgURI); + if (diagram == null) return 0; + return (int)diagram.getWidth(); + } + +// Draw the icon at the specified location. + public void paintComponent(Graphics gg) + { + super.paintComponent(gg); + + Graphics2D g = (Graphics2D)gg; + + Object oldAliasHint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); + + + SVGDiagram diagram = svgUniverse.getDiagram(svgURI); + if (diagram == null) return; + + if (!scaleToFit) + { + try + { + diagram.render(g); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAliasHint); + } + catch (SVGException e) + { + throw new RuntimeException(e); + } + return; + } + + Dimension dim = getSize(); + final int width = dim.width; + final int height = dim.height; +// int width = getWidth(); +// int height = getHeight(); + +// if (width == 0 || height == 0) +// { +// //Chances are we're rendering offscreen +// Dimension dim = getSize(); +// width = dim.width; +// height = dim.height; +// return; +// } + +// g.setClip(0, 0, dim.width, dim.height); + + + final Rectangle2D.Double rect = new Rectangle2D.Double(); + diagram.getViewRect(rect); + + scaleXform.setToScale(width / rect.width, height / rect.height); + + AffineTransform oldXform = g.getTransform(); + g.transform(scaleXform); + + try + { + diagram.render(g); + } + catch (SVGException e) + { + throw new RuntimeException(e); + } + + g.setTransform(oldXform); + + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAliasHint); + } + + public SVGUniverse getSvgUniverse() + { + return svgUniverse; + } + + public void setSvgUniverse(SVGUniverse svgUniverse) + { + SVGUniverse old = this.svgUniverse; + this.svgUniverse = svgUniverse; + firePropertyChange("svgUniverse", old, svgUniverse); + } + + public URI getSvgURI() + { + return svgURI; + } + + public void setSvgURI(URI svgURI) + { + URI old = this.svgURI; + this.svgURI = svgURI; + firePropertyChange("svgURI", old, svgURI); + } + + /** + * Most resources your component will want to access will be resources on your classpath. + * This method will interpret the passed string as a path in the classpath and use + * Class.getResource() to determine the URI of the SVG. + */ + public void setSvgResourcePath(String resourcePath) throws SVGException + { + URI old = this.svgURI; + + try + { + svgURI = new URI(getClass().getResource(resourcePath).toString()); +//System.err.println("SVGPanel: new URI " + svgURI + " from path " + resourcePath); + + firePropertyChange("svgURI", old, svgURI); + + repaint(); + } + catch (Exception e) + { + throw new SVGException("Could not resolve path " + resourcePath, e); +// svgURI = old; + } + } + + public boolean isScaleToFit() + { + return scaleToFit; + } + + public void setScaleToFit(boolean scaleToFit) + { + boolean old = this.scaleToFit; + this.scaleToFit = scaleToFit; + firePropertyChange("scaleToFit", old, scaleToFit); + } + + /** + * @return true if antiAliasing is turned on. + * @deprecated + */ + public boolean getUseAntiAlias() + { + return getAntiAlias(); + } + + /** + * @param antiAlias true to use antiAliasing. + * @deprecated + */ + public void setUseAntiAlias(boolean antiAlias) + { + setAntiAlias(antiAlias); + } + + /** + * @return true if antiAliasing is turned on. + */ + public boolean getAntiAlias() + { + return antiAlias; + } + + /** + * @param antiAlias true to use antiAliasing. + */ + public void setAntiAlias(boolean antiAlias) + { + boolean old = this.antiAlias; + this.antiAlias = antiAlias; + firePropertyChange("antiAlias", old, antiAlias); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() + { + + setLayout(new java.awt.BorderLayout()); + + } + // //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables + +} Index: core/src/com/kitfox/svg/app/data/HandlerFactory.java =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ core/src/com/kitfox/svg/app/data/HandlerFactory.java 2012-06-17 23:56:57.784545052 +0200 @@ -0,0 +1,27 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.kitfox.svg.app.data; + +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; + +/** + * + * @author kitfox + */ +public class HandlerFactory implements URLStreamHandlerFactory +{ + static Handler handler = new Handler(); + + public URLStreamHandler createURLStreamHandler(String protocol) + { + if ("data".equals(protocol)) + { + return handler; + } + return null; + } +}