Index: /trunk/patches/10trim_svgsalamander.patch
===================================================================
--- /trunk/patches/10trim_svgsalamander.patch	(revision 5283)
+++ /trunk/patches/10trim_svgsalamander.patch	(revision 5284)
@@ -1,5948 +1,5948 @@
 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: josm/src/com/kitfox/svg/animation/Animate.java
+Index: core/src/com/kitfox/svg/animation/Animate.java
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/Animate.java	2011-07-17 10:45:39.626276424 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,419 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/AnimateBase.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/AnimateBase.java	2011-07-17 10:45:40.086278706 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,133 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/AnimateColor.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/AnimateColor.java	2011-07-17 10:45:39.070273670 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,105 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/AnimateColorIface.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/AnimateColorIface.java	2011-07-17 10:45:41.886287631 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,38 +0,0 @@
--/*
-- * 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: josm/src/com/kitfox/svg/animation/AnimateMotion.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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/AnimateMotion.java	2011-07-17 10:45:39.186274242 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,282 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/AnimateTransform.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/AnimateTransform.java	2011-07-17 10:45:40.334279938 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,302 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/AnimateXform.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/AnimateXform.java	2011-07-17 10:45:41.418285313 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,54 +0,0 @@
--/*
-- * 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: josm/src/com/kitfox/svg/animation/AnimationElement.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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/AnimationElement.java	2011-07-17 10:45:38.918272914 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,414 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--public abstract class AnimationElement extends SVGElement
--{
--    protected String attribName;
--//    protected String attribType;
--    protected int attribType = AT_AUTO;
--
--    public static final int AT_CSS = 0;
--    public static final int AT_XML = 1;
--    public static final int AT_AUTO = 2;  //Check CSS first, then XML
--
--    protected TimeBase beginTime;
--    protected TimeBase durTime;
--    protected TimeBase endTime;
--    protected int fillType = FT_AUTO;
--
--    /** <a href="http://www.w3.org/TR/smil20/smil-timing.html#adef-fill">More about the <b>fill</b> attribute</a> */
--    public static final int FT_REMOVE = 0;
--    public static final int FT_FREEZE = 1;
--    public static final int FT_HOLD = 2;
--    public static final int FT_TRANSITION = 3;
--    public static final int FT_AUTO = 4;
--    public static final int FT_DEFAULT = 5;
--
--    /** Additive state of track */
--    public static final int AD_REPLACE = 0;
--    public static final int AD_SUM = 1;
--
--    int additiveType = AD_REPLACE;
--    
--    /** Accumlative state */
--    public static final int AC_REPLACE = 0;
--    public static final int AC_SUM = 1;
--
--    int accumulateType = AC_REPLACE;
--
--    /** Creates a new instance of AnimateEle */
--    public AnimationElement()
--    {
--    }
--
--    public static String animationElementToString(int attrValue)
--    {
--        switch (attrValue)
--        {
--            case AT_CSS:
--                return "CSS";
--            case AT_XML:
--                return "XML";
--            case AT_AUTO:
--                return "AUTO";
--            default:
--                throw new RuntimeException("Unknown element type");
--        }
--    }
--    
--    public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
--    {
--		//Load style string
--        super.loaderStartElement(helper, attrs, parent);
--
--        attribName = attrs.getValue("attributeName");
--        String attribType = attrs.getValue("attributeType");
--        if (attribType != null)
--        {
--            attribType = attribType.toLowerCase();
--            if (attribType.equals("css")) this.attribType = AT_CSS;
--            else if (attribType.equals("xml")) this.attribType = AT_XML;
--        }
--
--        String beginTime = attrs.getValue("begin");
--        String durTime = attrs.getValue("dur");
--        String endTime = attrs.getValue("end");
--
--        try
--        {
--            if (beginTime != null)
--            {
--                helper.animTimeParser.ReInit(new StringReader(beginTime));
--                this.beginTime = helper.animTimeParser.Expr();
--                this.beginTime.setParentElement(this);
--            }
--
--            if (durTime != null)
--            {
--                helper.animTimeParser.ReInit(new StringReader(durTime));
--                this.durTime = helper.animTimeParser.Expr();
--                this.durTime.setParentElement(this);
--            }
--
--            if (endTime != null)
--            {
--                helper.animTimeParser.ReInit(new StringReader(endTime));
--                this.endTime = helper.animTimeParser.Expr();
--                this.endTime.setParentElement(this);
--            }
--        }
--        catch (Exception e)
--        {
--            throw new SAXException(e);
--        }
--        
--//        this.beginTime = TimeBase.parseTime(beginTime);
--//        this.durTime = TimeBase.parseTime(durTime);
--//        this.endTime = TimeBase.parseTime(endTime);
--
--        String fill = attrs.getValue("fill");
--
--        if (fill != null)
--        {
--            if (fill.equals("remove")) this.fillType = FT_REMOVE;
--            if (fill.equals("freeze")) this.fillType = FT_FREEZE;
--            if (fill.equals("hold")) this.fillType = FT_HOLD;
--            if (fill.equals("transiton")) this.fillType = FT_TRANSITION;
--            if (fill.equals("auto")) this.fillType = FT_AUTO;
--            if (fill.equals("default")) this.fillType = FT_DEFAULT;
--        }
--        
--        String additiveStrn = attrs.getValue("additive");
--        
--        if (additiveStrn != null)
--        {
--            if (additiveStrn.equals("replace")) this.additiveType = AD_REPLACE;
--            if (additiveStrn.equals("sum")) this.additiveType = AD_SUM;
--        }
--        
--        String accumulateStrn = attrs.getValue("accumulate");
--        
--        if (accumulateStrn != null)
--        {
--            if (accumulateStrn.equals("replace")) this.accumulateType = AC_REPLACE;
--            if (accumulateStrn.equals("sum")) this.accumulateType = AC_SUM;
--        }
--    }
--
--    public String getAttribName() { return attribName; }
--    public int getAttribType() { return attribType; }
--    public int getAdditiveType() { return additiveType; }
--    public int getAccumulateType() { return accumulateType; }
--
--    public void evalParametric(AnimationTimeEval state, double curTime)
--    {
--        evalParametric(state, curTime, Double.NaN, Double.NaN);
--    }
--
--    /**
--     * Compares current time to start and end times and determines what degree
--     * of time interpolation this track currently represents.  Returns
--     * Float.NaN if this track cannot be evaluated at the passed time (ie,
--     * it is before or past the end of the track, or it depends upon
--     * an unknown event)
--     * @param state - A structure that will be filled with information
--     * regarding the applicability of this animatoin element at the passed
--     * time.
--     * @param curTime - Current time in seconds
--     * @param repeatCount - Optional number of repetitions of length 'dur' to
--     * do.  Set to Double.NaN to not consider this in the calculation.
--     * @param repeatDur - Optional amoun tof time to repeat the animaiton.
--     * Set to Double.NaN to not consider this in the calculation.
--     */
--    protected void evalParametric(AnimationTimeEval state, double curTime, double repeatCount, double repeatDur)
--    {
--        double begin = (beginTime == null) ? 0 : beginTime.evalTime();
--        if (Double.isNaN(begin) || begin > curTime)
--        {
--            state.set(Double.NaN, 0);
--            return;
--        }
--
--        double dur = (durTime == null) ? Double.NaN : durTime.evalTime();
--        if (Double.isNaN(dur))
--        {
--            state.set(Double.NaN, 0);
--            return;
--        }
--
--        //Determine end point of this animation
--        double end = (endTime == null) ? Double.NaN : endTime.evalTime();
--        double repeat;
--//        if (Double.isNaN(repeatDur))
--//        {
--//            repeatDur = dur;
--//        }
--        if (Double.isNaN(repeatCount) && Double.isNaN(repeatDur))
--        {
--            repeat = Double.NaN;
--        }
--        else
--        {
--            repeat = Math.min(
--                Double.isNaN(repeatCount) ? Double.POSITIVE_INFINITY : dur * repeatCount,
--                Double.isNaN(repeatDur) ? Double.POSITIVE_INFINITY : repeatDur);
--        }
--        if (Double.isNaN(repeat) && Double.isNaN(end))
--        {
--            //If neither and end point nor a repeat is specified, end point is 
--            // implied by duration.
--            end = begin + dur;
--        }
--
--        double finishTime;
--        if (Double.isNaN(end))
--        {
--            finishTime = begin + repeat;
--        }
--        else if (Double.isNaN(repeat))
--        {
--            finishTime = end;
--        }
--        else
--        {
--            finishTime = Math.min(end, repeat);
--        }
--        
--        double evalTime = Math.min(curTime, finishTime);
--//        if (curTime > finishTime) evalTime = finishTime;
--        
--        
--//        double evalTime = curTime;
--
--//        boolean pastEnd = curTime > evalTime;
--        
--//        if (!Double.isNaN(end) && curTime > end) { pastEnd = true; evalTime = Math.min(evalTime, end); }
--//        if (!Double.isNaN(repeat) && curTime > repeat) { pastEnd = true; evalTime = Math.min(evalTime, repeat); }
--        
--        double ratio = (evalTime - begin) / dur;
--        int rep = (int)ratio;
--        double interp = ratio - rep;
--        
--        //Adjust for roundoff
--        if (interp < 0.00001) interp = 0;
--
--//        state.set(interp, rep);
--//        if (!pastEnd)
--//        {
--//            state.set(interp, rep, false);
--//            return;
--//        }
--
--        //If we are still within the clip, return value
--        if (curTime == evalTime)
--        {
--            state.set(interp, rep);
--            return;
--        }
--        
--        //We are past end of clip.  Determine to clamp or ignore.
--        switch (fillType)
--        {
--            default:
--            case FT_REMOVE:
--            case FT_AUTO:
--            case FT_DEFAULT:
--                state.set(Double.NaN, rep);
--                return;
--            case FT_FREEZE:
--            case FT_HOLD:
--            case FT_TRANSITION:
--                state.set(interp == 0 ? 1 : interp, rep);
--                return;
--        }
--
--    }
--
--    double evalStartTime()
--    {
--        return beginTime == null ? Double.NaN : beginTime.evalTime();
--    }
--
--    double evalDurTime()
--    {
--        return durTime == null ? Double.NaN : durTime.evalTime();
--    }
--
--    /**
--     * Evaluates the ending time of this element.  Returns 0 if not specified.
--     *
--     * @see hasEndTime
--     */
--    double evalEndTime()
--    {
--        return endTime == null ? Double.NaN : endTime.evalTime();
--    }
--
--    /**
--     * Checks to see if an end time has been specified for this element.
--     */
--    boolean hasEndTime() { return endTime != null; }
--
--    /**
--     * Updates all attributes in this diagram associated with a time event.
--     * Ie, all attributes with track information.
--     * @return - true if this node has changed state as a result of the time
--     * update
--     */
--    public boolean updateTime(double curTime)
--    {
--        //Animation elements to not change with time
--        return false;
--    }
--
--    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: josm/src/com/kitfox/svg/animation/AnimationTimeEval.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++public abstract class AnimationElement extends SVGElement
++{
++    protected String attribName;
++//    protected String attribType;
++    protected int attribType = AT_AUTO;
++
++    public static final int AT_CSS = 0;
++    public static final int AT_XML = 1;
++    public static final int AT_AUTO = 2;  //Check CSS first, then XML
++
++    protected TimeBase beginTime;
++    protected TimeBase durTime;
++    protected TimeBase endTime;
++    protected int fillType = FT_AUTO;
++
++    /** <a href="http://www.w3.org/TR/smil20/smil-timing.html#adef-fill">More about the <b>fill</b> attribute</a> */
++    public static final int FT_REMOVE = 0;
++    public static final int FT_FREEZE = 1;
++    public static final int FT_HOLD = 2;
++    public static final int FT_TRANSITION = 3;
++    public static final int FT_AUTO = 4;
++    public static final int FT_DEFAULT = 5;
++
++    /** Additive state of track */
++    public static final int AD_REPLACE = 0;
++    public static final int AD_SUM = 1;
++
++    int additiveType = AD_REPLACE;
++    
++    /** Accumlative state */
++    public static final int AC_REPLACE = 0;
++    public static final int AC_SUM = 1;
++
++    int accumulateType = AC_REPLACE;
++
++    /** Creates a new instance of AnimateEle */
++    public AnimationElement()
++    {
++    }
++
++    public static String animationElementToString(int attrValue)
++    {
++        switch (attrValue)
++        {
++            case AT_CSS:
++                return "CSS";
++            case AT_XML:
++                return "XML";
++            case AT_AUTO:
++                return "AUTO";
++            default:
++                throw new RuntimeException("Unknown element type");
++        }
++    }
++    
++    public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
++    {
++		//Load style string
++        super.loaderStartElement(helper, attrs, parent);
++
++        attribName = attrs.getValue("attributeName");
++        String attribType = attrs.getValue("attributeType");
++        if (attribType != null)
++        {
++            attribType = attribType.toLowerCase();
++            if (attribType.equals("css")) this.attribType = AT_CSS;
++            else if (attribType.equals("xml")) this.attribType = AT_XML;
++        }
++
++        String beginTime = attrs.getValue("begin");
++        String durTime = attrs.getValue("dur");
++        String endTime = attrs.getValue("end");
++
++        try
++        {
++            if (beginTime != null)
++            {
++                helper.animTimeParser.ReInit(new StringReader(beginTime));
++                this.beginTime = helper.animTimeParser.Expr();
++                this.beginTime.setParentElement(this);
++            }
++
++            if (durTime != null)
++            {
++                helper.animTimeParser.ReInit(new StringReader(durTime));
++                this.durTime = helper.animTimeParser.Expr();
++                this.durTime.setParentElement(this);
++            }
++
++            if (endTime != null)
++            {
++                helper.animTimeParser.ReInit(new StringReader(endTime));
++                this.endTime = helper.animTimeParser.Expr();
++                this.endTime.setParentElement(this);
++            }
++        }
++        catch (Exception e)
++        {
++            throw new SAXException(e);
++        }
++        
++//        this.beginTime = TimeBase.parseTime(beginTime);
++//        this.durTime = TimeBase.parseTime(durTime);
++//        this.endTime = TimeBase.parseTime(endTime);
++
++        String fill = attrs.getValue("fill");
++
++        if (fill != null)
++        {
++            if (fill.equals("remove")) this.fillType = FT_REMOVE;
++            if (fill.equals("freeze")) this.fillType = FT_FREEZE;
++            if (fill.equals("hold")) this.fillType = FT_HOLD;
++            if (fill.equals("transiton")) this.fillType = FT_TRANSITION;
++            if (fill.equals("auto")) this.fillType = FT_AUTO;
++            if (fill.equals("default")) this.fillType = FT_DEFAULT;
++        }
++        
++        String additiveStrn = attrs.getValue("additive");
++        
++        if (additiveStrn != null)
++        {
++            if (additiveStrn.equals("replace")) this.additiveType = AD_REPLACE;
++            if (additiveStrn.equals("sum")) this.additiveType = AD_SUM;
++        }
++        
++        String accumulateStrn = attrs.getValue("accumulate");
++        
++        if (accumulateStrn != null)
++        {
++            if (accumulateStrn.equals("replace")) this.accumulateType = AC_REPLACE;
++            if (accumulateStrn.equals("sum")) this.accumulateType = AC_SUM;
++        }
++    }
++
++    public String getAttribName() { return attribName; }
++    public int getAttribType() { return attribType; }
++    public int getAdditiveType() { return additiveType; }
++    public int getAccumulateType() { return accumulateType; }
++
++    public void evalParametric(AnimationTimeEval state, double curTime)
++    {
++        evalParametric(state, curTime, Double.NaN, Double.NaN);
++    }
++
++    /**
++     * Compares current time to start and end times and determines what degree
++     * of time interpolation this track currently represents.  Returns
++     * Float.NaN if this track cannot be evaluated at the passed time (ie,
++     * it is before or past the end of the track, or it depends upon
++     * an unknown event)
++     * @param state - A structure that will be filled with information
++     * regarding the applicability of this animatoin element at the passed
++     * time.
++     * @param curTime - Current time in seconds
++     * @param repeatCount - Optional number of repetitions of length 'dur' to
++     * do.  Set to Double.NaN to not consider this in the calculation.
++     * @param repeatDur - Optional amoun tof time to repeat the animaiton.
++     * Set to Double.NaN to not consider this in the calculation.
++     */
++    protected void evalParametric(AnimationTimeEval state, double curTime, double repeatCount, double repeatDur)
++    {
++        double begin = (beginTime == null) ? 0 : beginTime.evalTime();
++        if (Double.isNaN(begin) || begin > curTime)
++        {
++            state.set(Double.NaN, 0);
++            return;
++        }
++
++        double dur = (durTime == null) ? Double.NaN : durTime.evalTime();
++        if (Double.isNaN(dur))
++        {
++            state.set(Double.NaN, 0);
++            return;
++        }
++
++        //Determine end point of this animation
++        double end = (endTime == null) ? Double.NaN : endTime.evalTime();
++        double repeat;
++//        if (Double.isNaN(repeatDur))
++//        {
++//            repeatDur = dur;
++//        }
++        if (Double.isNaN(repeatCount) && Double.isNaN(repeatDur))
++        {
++            repeat = Double.NaN;
++        }
++        else
++        {
++            repeat = Math.min(
++                Double.isNaN(repeatCount) ? Double.POSITIVE_INFINITY : dur * repeatCount,
++                Double.isNaN(repeatDur) ? Double.POSITIVE_INFINITY : repeatDur);
++        }
++        if (Double.isNaN(repeat) && Double.isNaN(end))
++        {
++            //If neither and end point nor a repeat is specified, end point is 
++            // implied by duration.
++            end = begin + dur;
++        }
++
++        double finishTime;
++        if (Double.isNaN(end))
++        {
++            finishTime = begin + repeat;
++        }
++        else if (Double.isNaN(repeat))
++        {
++            finishTime = end;
++        }
++        else
++        {
++            finishTime = Math.min(end, repeat);
++        }
++        
++        double evalTime = Math.min(curTime, finishTime);
++//        if (curTime > finishTime) evalTime = finishTime;
++        
++        
++//        double evalTime = curTime;
++
++//        boolean pastEnd = curTime > evalTime;
++        
++//        if (!Double.isNaN(end) && curTime > end) { pastEnd = true; evalTime = Math.min(evalTime, end); }
++//        if (!Double.isNaN(repeat) && curTime > repeat) { pastEnd = true; evalTime = Math.min(evalTime, repeat); }
++        
++        double ratio = (evalTime - begin) / dur;
++        int rep = (int)ratio;
++        double interp = ratio - rep;
++        
++        //Adjust for roundoff
++        if (interp < 0.00001) interp = 0;
++
++//        state.set(interp, rep);
++//        if (!pastEnd)
++//        {
++//            state.set(interp, rep, false);
++//            return;
++//        }
++
++        //If we are still within the clip, return value
++        if (curTime == evalTime)
++        {
++            state.set(interp, rep);
++            return;
++        }
++        
++        //We are past end of clip.  Determine to clamp or ignore.
++        switch (fillType)
++        {
++            default:
++            case FT_REMOVE:
++            case FT_AUTO:
++            case FT_DEFAULT:
++                state.set(Double.NaN, rep);
++                return;
++            case FT_FREEZE:
++            case FT_HOLD:
++            case FT_TRANSITION:
++                state.set(interp == 0 ? 1 : interp, rep);
++                return;
++        }
++
++    }
++
++    double evalStartTime()
++    {
++        return beginTime == null ? Double.NaN : beginTime.evalTime();
++    }
++
++    double evalDurTime()
++    {
++        return durTime == null ? Double.NaN : durTime.evalTime();
++    }
++
++    /**
++     * Evaluates the ending time of this element.  Returns 0 if not specified.
++     *
++     * @see hasEndTime
++     */
++    double evalEndTime()
++    {
++        return endTime == null ? Double.NaN : endTime.evalTime();
++    }
++
++    /**
++     * Checks to see if an end time has been specified for this element.
++     */
++    boolean hasEndTime() { return endTime != null; }
++
++    /**
++     * Updates all attributes in this diagram associated with a time event.
++     * Ie, all attributes with track information.
++     * @return - true if this node has changed state as a result of the time
++     * update
++     */
++    public boolean updateTime(double curTime)
++    {
++        //Animation elements to not change with time
++        return false;
++    }
++
++    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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/AnimationTimeEval.java	2011-07-17 10:45:41.530285870 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,65 +0,0 @@
--/*
-- * 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: josm/src/com/kitfox/svg/animation/Bezier.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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/Bezier.java	2011-07-17 10:45:38.790272277 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,201 +0,0 @@
--/*
-- * 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: josm/src/com/kitfox/svg/animation/SetSmil.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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/SetSmil.java	2011-07-17 10:45:40.546280989 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,73 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/TimeBase.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/TimeBase.java	2011-07-17 10:45:40.206279304 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,99 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/TimeCompound.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/TimeCompound.java	2011-07-17 10:45:41.758286997 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,84 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/TimeDiscrete.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/TimeDiscrete.java	2011-07-17 10:45:40.830282393 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,51 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/TimeIndefinite.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/TimeIndefinite.java	2011-07-17 10:45:39.346275036 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,48 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--public class TimeIndefinite extends TimeBase
--{
--    
--    /** Creates a new instance of TimeDiscrete */
--    public TimeIndefinite()
--    {
--    }
--    
--    public double evalTime()
--    {
--        return Double.POSITIVE_INFINITY;
--    }
--    
--}
-Index: josm/src/com/kitfox/svg/animation/TimeLookup.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/TimeLookup.java	2011-07-17 10:45:40.698281743 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,75 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/TimeSum.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/TimeSum.java	2011-07-17 10:45:39.754277058 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,60 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/TrackBase.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/TrackBase.java	2011-07-17 10:45:41.126283861 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,103 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/TrackColor.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/TrackColor.java	2011-07-17 10:45:41.638286404 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,95 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/TrackDouble.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/TrackDouble.java	2011-07-17 10:45:39.874277657 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,119 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/TrackManager.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/TrackManager.java	2011-07-17 10:45:41.278284615 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,153 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/TrackMotion.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/TrackMotion.java	2011-07-17 10:45:40.966283072 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,128 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/TrackPath.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/TrackPath.java	2011-07-17 10:45:40.446280495 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,100 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/animation/TrackTransform.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/animation/TrackTransform.java	2011-07-17 10:45:39.458275590 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,112 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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: josm/src/com/kitfox/svg/SVGElement.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/SVGElement.java	2011-07-17 10:45:42.254289456 +0200
-+++ josm/src/com/kitfox/svg/SVGElement.java	2011-07-17 10:58:55.622223558 +0200
-@@ -33,7 +33,6 @@
+--- 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.animation.*;
  import com.kitfox.svg.pathcmd.*;
  import com.kitfox.svg.xml.*;
  import java.io.Serializable;
-@@ -101,8 +100,6 @@
+@@ -100,6 +101,8 @@
       */
  //    protected SVGUniverse universe;
      
--    protected final TrackManager trackManager = new TrackManager();
--
++    protected final TrackManager trackManager = new TrackManager();
++
      boolean dirty = true;
  
  //    public static final Matcher adobeId = Pattern.compile("(.*)_1_").matcher("");
-@@ -268,46 +265,6 @@
+@@ -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);
--    }
--    
++    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
       */
-@@ -333,12 +290,6 @@
+@@ -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);
--        }
++        
++        //Add info to track if we've scanned animation element
++        if (child instanceof AnimationElement)
++        {
++            trackManager.addTrackElement((AnimationElement)child);
++        }
      }
      
      private void setDiagram(SVGDiagram diagram)
-@@ -457,54 +408,6 @@
+@@ -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);
--    }
--    
++    
++    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
-@@ -524,14 +427,6 @@
+@@ -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;
--        }
--        
++        //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;
          
-@@ -544,14 +439,6 @@
+@@ -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;
--        }
--        
++        //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;
          
-@@ -593,14 +480,6 @@
+@@ -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;
--        }
--        
++        //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: josm/src/com/kitfox/svg/SVGLoader.java
+Index: core/src/com/kitfox/svg/SVGLoader.java
 ===================================================================
---- josm.orig/src/com/kitfox/svg/SVGLoader.java	2011-07-17 10:45:36.750262161 +0200
-+++ josm/src/com/kitfox/svg/SVGLoader.java	2011-07-17 10:54:22.172867591 +0200
-@@ -33,8 +33,6 @@
+--- 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.*;
--
++import com.kitfox.svg.animation.*;
++
  /**
   * @author Mark McKay
   * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
-@@ -77,10 +75,6 @@
+@@ -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("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);
-@@ -104,7 +98,6 @@
+@@ -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("set", SetSmil.class);
          nodeClasses.put("shape", ShapeElement.class);
          nodeClasses.put("stop", Stop.class);
          nodeClasses.put("style", Style.class);
-Index: josm/src/com/kitfox/svg/SVGLoaderHelper.java
+Index: core/src/com/kitfox/svg/SVGLoaderHelper.java
 ===================================================================
---- josm.orig/src/com/kitfox/svg/SVGLoaderHelper.java	2011-07-17 10:45:49.470325238 +0200
-+++ josm/src/com/kitfox/svg/SVGLoaderHelper.java	2011-07-17 10:53:36.972643458 +0200
-@@ -28,9 +28,6 @@
+--- 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.*;
++import java.io.*;
++
++import com.kitfox.svg.animation.parser.*;
  
  /**
   * @author Mark McKay
-@@ -50,11 +47,6 @@
+@@ -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(""));
--    
++    /**
++     * 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: josm/src/com/kitfox/svg/app/MainFrame.java
+Index: core/src/com/kitfox/svg/app/MainFrame.java
 ===================================================================
---- josm.orig/src/com/kitfox/svg/app/MainFrame.java	2011-07-17 10:45:46.642311212 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,134 +0,0 @@
--/*
-- * 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: josm/src/com/kitfox/svg/app/PlayerDialog.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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/app/PlayerDialog.java	2011-07-17 10:45:47.014313062 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,289 +0,0 @@
--/*
-- * 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.
--     */
--    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//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();
--    }// </editor-fold>//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: josm/src/com/kitfox/svg/app/PlayerThread.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.
++     */
++    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//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();
++    }// </editor-fold>//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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/app/PlayerThread.java	2011-07-17 10:45:47.598315958 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,129 +0,0 @@
--/*
-- * 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: josm/src/com/kitfox/svg/app/PlayerThreadListener.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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/app/PlayerThreadListener.java	2011-07-17 10:45:47.466315300 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,37 +0,0 @@
--/*
-- * 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: josm/src/com/kitfox/svg/app/SVGPlayer.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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/app/SVGPlayer.java	2011-07-17 10:45:48.234319110 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,436 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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.
--     */
--    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//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();
--    }// </editor-fold>//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: josm/src/com/kitfox/svg/app/SVGViewer.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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.
++     */
++    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//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();
++    }// </editor-fold>//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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/app/SVGViewer.java	2011-07-17 10:45:47.318314570 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,432 +0,0 @@
--/*
-- * 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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
-- */
--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.
--     */
--    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//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();
--    }// </editor-fold>//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: josm/src/com/kitfox/svg/app/VersionDialog.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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
++ */
++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.
++     */
++    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//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();
++    }// </editor-fold>//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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/app/VersionDialog.java	2011-07-17 10:45:48.410319985 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,151 +0,0 @@
--/*
-- * 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.
--     */
--    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//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();
--    }
--    // </editor-fold>//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: josm/src/com/kitfox/svg/app/ant/SVGToImageAntTask.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.
++     */
++    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//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();
++    }
++    // </editor-fold>//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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/app/ant/SVGToImageAntTask.java	2011-07-17 10:45:47.158313776 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,251 +0,0 @@
--/*
-- * 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;
--
--/**
-- * <p>Translates a group of SVG files into images.</p>
-- * 
-- * <p>Parameters:</p>
-- * <p><ul>
-- * <li/>destDir - If present, specifices a directory to write SVG files to.  Otherwise
-- * writes images to directory SVG file was found in
-- * verbose - If true, prints processing information to the console
-- * <li/>format - File format for output images.  The java core javax.imageio.ImageIO
-- * class is used for creating images, so format strings will depend on what
-- * files your system is configured to handle.  By default, "gif", "jpg" and "png"
-- * files are guaranteed to be present.  If omitted, "png" is used by default.
-- * <li/>backgroundColor - Optional background color.  Color can be specified as a standard 
-- * HTML color.  That is, as the name of a standard color such as "blue" or 
-- * "limegreen", using the # notaion as in #ff00ff for magenta, or in rgb format
-- * listing the components as in rgb(255, 192, 192) for pink.  If omitted,
-- * background is transparent.
-- * <li/>antiAlias - If set, shapes are drawn using antialiasing.  Defaults to true.
-- * <li/>interpolation - String describing image interpolation alrogithm.  Can
-- * be one of "nearest neighbor", "bilinear" or "bicubic".  Defaults to "bicubic".
-- * <li/>width - If greater than 0, determines the width of the written image.  Otherwise,
-- * the width is obtained from the SVG document.  Defaults to -1;
-- * <li/>height - If greater than 0, determines the height of the written image.  Otherwise,
-- * the height is obtained from the SVG document.  Defaults to -1.
-- * <li/>sizeToFit - If true and the width and height of the output image differ
-- * from that of the SVG image, the valid area of the SVG image will be resized 
-- * to fit the specified size.
-- * <li/>verbose - IF true, prints out diagnostic infromation about processing.  
-- * Defaults to false.
-- * </ul></p>
-- * 
-- * Example:
-- * &lt;SVGToImage destDir="${index.java}" format="jpg" verbose="true"&gt;
-- *    &lt;fileset dir="${dir1}"&gt;
-- *        &lt;include name="*.svg"/&gt;
-- *    &lt;/fileset&gt;
-- *    &lt;fileset dir="${dir2}"&gt;
-- *        &lt;include name="*.svg"/&gt;
-- *    &lt;/fileset&gt;
-- * &lt;/SVGToImage&gt;
-- * 
-- * 
-- * 
-- * @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: josm/src/com/kitfox/svg/app/beans/ProportionalLayoutPanel.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;
++
++/**
++ * <p>Translates a group of SVG files into images.</p>
++ * 
++ * <p>Parameters:</p>
++ * <p><ul>
++ * <li/>destDir - If present, specifices a directory to write SVG files to.  Otherwise
++ * writes images to directory SVG file was found in
++ * verbose - If true, prints processing information to the console
++ * <li/>format - File format for output images.  The java core javax.imageio.ImageIO
++ * class is used for creating images, so format strings will depend on what
++ * files your system is configured to handle.  By default, "gif", "jpg" and "png"
++ * files are guaranteed to be present.  If omitted, "png" is used by default.
++ * <li/>backgroundColor - Optional background color.  Color can be specified as a standard 
++ * HTML color.  That is, as the name of a standard color such as "blue" or 
++ * "limegreen", using the # notaion as in #ff00ff for magenta, or in rgb format
++ * listing the components as in rgb(255, 192, 192) for pink.  If omitted,
++ * background is transparent.
++ * <li/>antiAlias - If set, shapes are drawn using antialiasing.  Defaults to true.
++ * <li/>interpolation - String describing image interpolation alrogithm.  Can
++ * be one of "nearest neighbor", "bilinear" or "bicubic".  Defaults to "bicubic".
++ * <li/>width - If greater than 0, determines the width of the written image.  Otherwise,
++ * the width is obtained from the SVG document.  Defaults to -1;
++ * <li/>height - If greater than 0, determines the height of the written image.  Otherwise,
++ * the height is obtained from the SVG document.  Defaults to -1.
++ * <li/>sizeToFit - If true and the width and height of the output image differ
++ * from that of the SVG image, the valid area of the SVG image will be resized 
++ * to fit the specified size.
++ * <li/>verbose - IF true, prints out diagnostic infromation about processing.  
++ * Defaults to false.
++ * </ul></p>
++ * 
++ * Example:
++ * &lt;SVGToImage destDir="${index.java}" format="jpg" verbose="true"&gt;
++ *    &lt;fileset dir="${dir1}"&gt;
++ *        &lt;include name="*.svg"/&gt;
++ *    &lt;/fileset&gt;
++ *    &lt;fileset dir="${dir2}"&gt;
++ *        &lt;include name="*.svg"/&gt;
++ *    &lt;/fileset&gt;
++ * &lt;/SVGToImage&gt;
++ * 
++ * 
++ * 
++ * @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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/app/beans/ProportionalLayoutPanel.java	2011-07-17 10:45:47.946317682 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,91 +0,0 @@
--/*
-- * 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.
--     */
--    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//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);
--
--    }
--    // </editor-fold>//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: josm/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/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.
++     */
++    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//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);
++
++    }
++    // </editor-fold>//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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/app/beans/SVGPanel.java	2011-07-17 10:45:47.806316985 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,243 +0,0 @@
--/*
-- * 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.
--     */
--    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
--    private void initComponents()
--    {
--
--        setLayout(new java.awt.BorderLayout());
--
--    }
--    // </editor-fold>//GEN-END:initComponents
--    
--    
--    // Variables declaration - do not modify//GEN-BEGIN:variables
--    // End of variables declaration//GEN-END:variables
--    
--}
-Index: josm/src/com/kitfox/svg/app/data/HandlerFactory.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.
++     */
++    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
++    private void initComponents()
++    {
++
++        setLayout(new java.awt.BorderLayout());
++
++    }
++    // </editor-fold>//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
 ===================================================================
---- josm.orig/src/com/kitfox/svg/app/data/HandlerFactory.java	2011-07-17 10:45:46.898312484 +0200
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,27 +0,0 @@
--/*
-- * 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;
--    }
--}
+--- /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;
++    }
++}
Index: /trunk/patches/20svgsalamander_getxform.patch
===================================================================
--- /trunk/patches/20svgsalamander_getxform.patch	(revision 5283)
+++ /trunk/patches/20svgsalamander_getxform.patch	(revision 5284)
@@ -1,16 +1,16 @@
 Patch against rev 98 of https://svn.java.net/svn/svgsalamander~svn/trunk. Adds getXForm() method needed for the importvec plugin.
-Index: josm/src/com/kitfox/svg/TransformableElement.java
+Index: core/src/com/kitfox/svg/TransformableElement.java
 ===================================================================
---- josm.orig/src/com/kitfox/svg/TransformableElement.java
-+++ josm/src/com/kitfox/svg/TransformableElement.java
-@@ -53,6 +54,11 @@
+--- core.orig/src/com/kitfox/svg/TransformableElement.java	2012-05-11 17:03:52.404311564 +0200
++++ core/src/com/kitfox/svg/TransformableElement.java	2012-06-18 00:00:20.444550308 +0200
+@@ -53,11 +53,6 @@
      {
          super(id, parent);
      }
-+
-+    public AffineTransform getXForm()
-+    {
-+        return xform;
-+    }
+-
+-    public AffineTransform getXForm()
+-    {
+-        return xform;
+-    }
  /*
      public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent)
