Index: /trunk/images/presets/lottery.svg
===================================================================
--- /trunk/images/presets/lottery.svg	(revision 7675)
+++ /trunk/images/presets/lottery.svg	(revision 7676)
@@ -1,347 +1,1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://web.resource.org/cc/"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="64"
-   height="64"
-   id="svg1307"
-   sodipodi:version="0.32"
-   inkscape:version="0.43"
-   version="1.0"
-   sodipodi:docbase="/tmp/wikinews"
-   sodipodi:docname="Lotto-v1.svg">
-  <defs
-     id="defs1309" />
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="4"
-     inkscape:cx="30.25"
-     inkscape:cy="23.910307"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:document-units="px"
-     inkscape:grid-bbox="true"
-     inkscape:window-width="984"
-     inkscape:window-height="719"
-     inkscape:window-x="0"
-     inkscape:window-y="0" />
-  <metadata
-     id="metadata1312">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     id="layer1"
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer">
-    <g
-       id="g6865">
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="-1.3614551"
-         x="10.326274"
-         height="34"
-         width="50.067074"
-         id="rect2216"
-         style="fill:#d99f9f;fill-opacity:1;stroke:#000000;stroke-width:0.93292624;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="0.60500801"
-         x="20.35981"
-         height="6"
-         width="6"
-         id="rect2224"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="0.60500801"
-         x="28.35981"
-         height="6"
-         width="6"
-         id="rect2226"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="0.60500801"
-         x="36.35981"
-         height="6"
-         width="6"
-         id="rect2228"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="0.60500801"
-         x="44.35981"
-         height="6"
-         width="6"
-         id="rect2235"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="0.60500801"
-         x="12.359811"
-         height="6"
-         width="6"
-         id="rect2286"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="0.60500801"
-         x="52.35981"
-         height="6"
-         width="6"
-         id="rect2288"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="8.6050081"
-         x="20.35981"
-         height="6"
-         width="6"
-         id="rect2290"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="8.6050081"
-         x="28.35981"
-         height="6"
-         width="6"
-         id="rect2292"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="8.6050081"
-         x="36.359814"
-         height="6"
-         width="6"
-         id="rect2294"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="8.6050081"
-         x="44.359814"
-         height="6"
-         width="6"
-         id="rect2296"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="8.6050081"
-         x="12.359811"
-         height="6"
-         width="6"
-         id="rect2298"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="8.6050081"
-         x="52.359814"
-         height="6"
-         width="6"
-         id="rect2300"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="16.605007"
-         x="20.359804"
-         height="6"
-         width="6"
-         id="rect2302"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="16.605007"
-         x="28.359804"
-         height="6"
-         width="6"
-         id="rect2304"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="16.605007"
-         x="36.35981"
-         height="6"
-         width="6"
-         id="rect2306"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="16.605007"
-         x="44.35981"
-         height="6"
-         width="6"
-         id="rect2308"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="16.605007"
-         x="12.359806"
-         height="6"
-         width="6"
-         id="rect2310"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="16.605007"
-         x="52.35981"
-         height="6"
-         width="6"
-         id="rect2312"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="24.605007"
-         x="20.35981"
-         height="6"
-         width="6"
-         id="rect2314"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="24.605007"
-         x="28.35981"
-         height="6"
-         width="6"
-         id="rect2316"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="24.605007"
-         x="36.359818"
-         height="6"
-         width="6"
-         id="rect2318"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="24.605007"
-         x="44.359814"
-         height="6"
-         width="6"
-         id="rect2320"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="24.605007"
-         x="12.359812"
-         height="6"
-         width="6"
-         id="rect2322"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <rect
-         transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
-         y="24.605007"
-         x="52.359814"
-         height="6"
-         width="6"
-         id="rect2324"
-         style="fill:none;fill-opacity:1;stroke:#b50023;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <path
-         id="path4082"
-         d="M 11.394423,3.291391 C 13.19723,7.6344064 14.111461,10.595961 15.865574,13.305076 C 16.073049,13.625509 16.407577,13.842783 16.678578,14.111636"
-         style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-      <path
-         id="path4084"
-         d="M 16.904272,5.868514 C 17.309376,6.4941709 15.445697,6.1804209 14.708993,6.293661 C 12.874321,6.5756717 11.899317,9.161173 10.609804,9.8182242"
-         style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-    </g>
-    <g
-       id="g6894"
-       transform="translate(-0.163838,-37.41383)">
-      <g
-         transform="matrix(1.310345,0,0,1.310345,-27.2672,12.59487)"
-         id="g4137">
-        <path
-           sodipodi:type="arc"
-           style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.76315778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-           id="path1315"
-           sodipodi:cx="19.710602"
-           sodipodi:cy="30.85437"
-           sodipodi:rx="6.805903"
-           sodipodi:ry="6.805903"
-           d="M 26.516505 30.85437 A 6.805903 6.805903 0 1 1  12.904699,30.85437 A 6.805903 6.805903 0 1 1  26.516505 30.85437 z"
-           transform="translate(33.5953,16.45153)" />
-        <text
-           xml:space="preserve"
-           style="font-size:6px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-           x="49.560547"
-           y="49.453125"
-           id="text2212"
-           sodipodi:linespacing="125%"><tspan
-             sodipodi:role="line"
-             id="tspan2214"
-             x="49.560547"
-             y="49.453125">23</tspan></text>
-      </g>
-      <g
-         transform="matrix(1.310345,0,0,1.310345,-0.646509,6.456979)"
-         id="g4127">
-        <path
-           sodipodi:type="arc"
-           style="font-size:8px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.76315778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
-           id="path2202"
-           sodipodi:cx="19.710602"
-           sodipodi:cy="30.85437"
-           sodipodi:rx="6.805903"
-           sodipodi:ry="6.805903"
-           d="M 26.516505 30.85437 A 6.805903 6.805903 0 1 1  12.904699,30.85437 A 6.805903 6.805903 0 1 1  26.516505 30.85437 z"
-           transform="translate(2.595301,21.45153)" />
-        <text
-           xml:space="preserve"
-           style="font-size:4.94748735px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-           x="39.434193"
-           y="58.444778"
-           id="text2204"
-           sodipodi:linespacing="100%"
-           transform="matrix(1.143483,0.274659,-0.403949,0.777495,0,0)"><tspan
-             sodipodi:role="line"
-             id="tspan2206"
-             x="39.434193"
-             y="58.444778">12</tspan></text>
-      </g>
-      <g
-         transform="matrix(1.310345,0,0,1.310345,4.353479,2.465499)"
-         id="g4132">
-        <path
-           sodipodi:type="arc"
-           style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.76315778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-           id="path2198"
-           sodipodi:cx="19.710602"
-           sodipodi:cy="30.85437"
-           sodipodi:rx="6.805903"
-           sodipodi:ry="6.805903"
-           d="M 26.516505 30.85437 A 6.805903 6.805903 0 1 1  12.904699,30.85437 A 6.805903 6.805903 0 1 1  26.516505 30.85437 z"
-           transform="translate(17.9835,18.83973)" />
-        <text
-           xml:space="preserve"
-           style="font-size:5.03230143px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-           x="45.061573"
-           y="43.613289"
-           id="text2208"
-           sodipodi:linespacing="125%"
-           transform="scale(0.838717,1.192297)"><tspan
-             sodipodi:role="line"
-             id="tspan2210"
-             x="45.061573"
-             y="43.613289">42</tspan></text>
-      </g>
-    </g>
-  </g>
-</svg>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path id="0" d="M26.516505 30.85437A6.805903 6.805903 0 1 1 12.904699 30.85437 6.805903 6.805903 0 1 1 26.516505 30.85437z" stroke-width=".763" stroke="#000" fill="#fff"/></defs><g transform="matrix(.96314.269-.269.96314 0 0)"><path fill="#d99f9f" stroke="#000" stroke-width=".933" d="m10.326-1.361h50.07v34h-50.07z"/><g fill="none" stroke="#b50023"><path d="m20.36.605h6v6h-6z"/><path d="m28.36.605h6v6h-6z"/><path d="m36.36.605h6v6h-6z"/><path d="m44.36.605h6v6h-6z"/><path d="m12.36.605h6v6h-6z"/><path d="m52.36.605h6v6h-6z"/><path d="m20.36 8.605h6v6h-6z"/><path d="m28.36 8.605h6v6h-6z"/><path d="m36.36 8.605h6v6h-6z"/><path d="m44.36 8.605h6v6h-6z"/><path d="m12.36 8.605h6v6h-6z"/><path d="m52.36 8.605h6v6h-6z"/><path d="m20.36 16.605h6v6h-6z"/><path d="m28.36 16.605h6v6h-6z"/><path d="m36.36 16.605h6v6h-6z"/><path d="m44.36 16.605h6v6h-6z"/><path d="m12.36 16.605h6v6h-6z"/><path d="m52.36 16.605h6v6h-6z"/><path d="m20.36 24.605h6v6h-6z"/><path d="m28.36 24.605h6v6h-6z"/><path d="m36.36 24.605h6v6h-6z"/><path d="m44.36 24.605h6v6h-6z"/><path d="m12.36 24.605h6v6h-6z"/><path d="m52.36 24.605h6v6h-6z"/></g></g><g fill="none" fill-rule="evenodd" stroke="#000" fill-opacity=".75"><path d="m11.394 3.291c1.803 4.343 2.717 7.305 4.471 10.01.207.32.542.538.813.807"/><path d="m16.904 5.869c.405.626-1.459.312-2.195.425-1.835.282-2.81 2.868-4.099 3.525"/></g><g transform="translate(-.164-37.414)"><g transform="matrix(1.31035 0 0 1.31035-27.27 12.595)"><use transform="translate(33.595 16.452)" xlink:href="#0"/><text x="49.561" y="49.45" font-family="Bitstream Vera Sans" text-align="start" line-height="125%" font-size="6"><tspan x="49.561" y="49.45">23</tspan></text></g><g transform="matrix(1.31035 0 0 1.31035-.647 6.457)"><use transform="translate(2.595 21.452)" xlink:href="#0"/><text x="39.434" y="58.44" transform="matrix(1.14348.27466-.40395.7775 0 0)" font-family="Bitstream Vera Sans" text-anchor="middle" text-align="center" line-height="100%" font-size="4.947"><tspan x="39.434" y="58.44">12</tspan></text></g><g transform="matrix(1.31035 0 0 1.31035 4.353 2.465)"><use transform="translate(17.984 18.84)" xlink:href="#0"/><text x="45.06" y="43.613" transform="scale(.83872 1.1923)" font-family="Bitstream Vera Sans" text-align="start" line-height="125%" font-size="5.03"><tspan x="45.06" y="43.613">42</tspan></text></g></g></svg>
Index: /trunk/patches/10trim_svgsalamander.patch
===================================================================
--- /trunk/patches/10trim_svgsalamander.patch	(revision 7675)
+++ /trunk/patches/10trim_svgsalamander.patch	(revision 7676)
@@ -1,5948 +1,301 @@
-Patch against rev 98 of https://svn.java.net/svn/svgsalamander~svn/trunk. It strips some classes, that aren't needed (basically animation and gui) and removes dependencies. The only purpose of this patch is to reduce binary download size for JOSM users.
-Index: core/src/com/kitfox/svg/animation/Animate.java
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ core/src/com/kitfox/svg/animation/Animate.java	2012-06-17 23:56:57.664545050 +0200
-@@ -0,0 +1,419 @@
-+/*
-+ * Animate.java
-+ *
-+ *  The Salamander Project - 2D and 3D graphics libraries in Java
-+ *  Copyright (C) 2004 Mark McKay
-+ *
-+ *  This library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public
-+ *  License as published by the Free Software Foundation; either
-+ *  version 2.1 of the License, or (at your option) any later version.
-+ *
-+ *  This library is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ *  Lesser General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU Lesser General Public
-+ *  License along with this library; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
-+ *  projects can be found at http://www.kitfox.com
-+ *
-+ * Created on August 15, 2004, 2:51 AM
-+ */
-+
-+package com.kitfox.svg.animation;
-+
-+import com.kitfox.svg.SVGElement;
-+import com.kitfox.svg.SVGException;
-+import com.kitfox.svg.SVGLoaderHelper;
-+import com.kitfox.svg.animation.parser.AnimTimeParser;
-+import com.kitfox.svg.xml.ColorTable;
-+import com.kitfox.svg.xml.StyleAttribute;
-+import com.kitfox.svg.xml.XMLParseUtil;
-+import java.awt.Color;
-+import java.awt.geom.AffineTransform;
-+import java.awt.geom.GeneralPath;
-+import java.awt.geom.PathIterator;
-+import org.xml.sax.Attributes;
-+import org.xml.sax.SAXException;
-+
-+
-+/**
-+ * Animate is a really annoying morphic tag that could represent a real value,
-+ * a color or a path
-+ *
-+ * @author Mark McKay
-+ * @author <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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ core/src/com/kitfox/svg/animation/AnimateColorIface.java	2012-06-17 23:56:57.672545050 +0200
-@@ -0,0 +1,38 @@
-+/*
-+ * AnimateColorIface.java
-+ *
-+ *  The Salamander Project - 2D and 3D graphics libraries in Java
-+ *  Copyright (C) 2004 Mark McKay
-+ *
-+ *  This library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public
-+ *  License as published by the Free Software Foundation; either
-+ *  version 2.1 of the License, or (at your option) any later version.
-+ *
-+ *  This library is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ *  Lesser General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU Lesser General Public
-+ *  License along with this library; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
-+ *  projects can be found at http://www.kitfox.com
-+ *
-+ * Created on January 16, 2005, 6:24 AM
-+ */
-+
-+package com.kitfox.svg.animation;
-+
-+import java.awt.*;
-+
-+/**
-+ *
-+ * @author kitfox
-+ */
-+public interface AnimateColorIface
-+{
-+    public Color evalColor(double interp);
-+}
-Index: core/src/com/kitfox/svg/animation/AnimateMotion.java
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ core/src/com/kitfox/svg/animation/AnimateMotion.java	2012-06-17 23:56:57.672545050 +0200
-@@ -0,0 +1,282 @@
-+/*
-+ * Animate.java
-+ *
-+ *  The Salamander Project - 2D and 3D graphics libraries in Java
-+ *  Copyright (C) 2004 Mark McKay
-+ *
-+ *  This library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public
-+ *  License as published by the Free Software Foundation; either
-+ *  version 2.1 of the License, or (at your option) any later version.
-+ *
-+ *  This library is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ *  Lesser General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU Lesser General Public
-+ *  License along with this library; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
-+ *  projects can be found at http://www.kitfox.com
-+ *
-+ * Created on August 15, 2004, 2:51 AM
-+ */
-+
-+package com.kitfox.svg.animation;
-+
-+import com.kitfox.svg.SVGElement;
-+import com.kitfox.svg.SVGException;
-+import com.kitfox.svg.SVGLoaderHelper;
-+import com.kitfox.svg.animation.parser.AnimTimeParser;
-+import com.kitfox.svg.xml.StyleAttribute;
-+import java.awt.geom.AffineTransform;
-+import java.awt.geom.GeneralPath;
-+import java.awt.geom.PathIterator;
-+import java.awt.geom.Point2D;
-+import java.util.ArrayList;
-+import java.util.Iterator;
-+import java.util.regex.Matcher;
-+import java.util.regex.Pattern;
-+import org.xml.sax.Attributes;
-+import org.xml.sax.SAXException;
-+
-+
-+/**
-+ * @author Mark McKay
-+ * @author <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
-===================================================================
---- /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
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ core/src/com/kitfox/svg/animation/AnimateXform.java	2012-06-17 23:56:57.676545050 +0200
-@@ -0,0 +1,54 @@
-+/*
-+ * AnimateXform.java
-+ *
-+ *  The Salamander Project - 2D and 3D graphics libraries in Java
-+ *  Copyright (C) 2004 Mark McKay
-+ *
-+ *  This library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public
-+ *  License as published by the Free Software Foundation; either
-+ *  version 2.1 of the License, or (at your option) any later version.
-+ *
-+ *  This library is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ *  Lesser General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU Lesser General Public
-+ *  License along with this library; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
-+ *  projects can be found at http://www.kitfox.com
-+ *
-+ * Created on January 14, 2005, 6:46 AM
-+ */
-+
-+package com.kitfox.svg.animation;
-+
-+import com.kitfox.svg.SVGElement;
-+import com.kitfox.svg.SVGLoaderHelper;
-+import java.awt.geom.AffineTransform;
-+import org.xml.sax.Attributes;
-+import org.xml.sax.SAXException;
-+
-+
-+
-+/**
-+ *
-+ * @author kitfox
-+ */
-+abstract public class AnimateXform extends AnimateBase
-+{
-+    public AnimateXform()
-+    {
-+    }
-+    
-+    public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
-+    {
-+        super.loaderStartElement(helper, attrs, parent);
-+    }
-+    
-+    abstract public AffineTransform eval(AffineTransform xform, double interp);
-+    
-+}
-Index: core/src/com/kitfox/svg/animation/AnimationElement.java
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ core/src/com/kitfox/svg/animation/AnimationElement.java	2012-06-17 23:56:57.676545050 +0200
-@@ -0,0 +1,414 @@
-+/*
-+ * AnimateEle.java
-+ *
-+ *  The Salamander Project - 2D and 3D graphics libraries in Java
-+ *  Copyright (C) 2004 Mark McKay
-+ *
-+ *  This library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public
-+ *  License as published by the Free Software Foundation; either
-+ *  version 2.1 of the License, or (at your option) any later version.
-+ *
-+ *  This library is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ *  Lesser General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU Lesser General Public
-+ *  License along with this library; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
-+ *  projects can be found at http://www.kitfox.com
-+ *
-+ * Created on August 15, 2004, 2:52 AM
-+ */
-+
-+package com.kitfox.svg.animation;
-+
-+import com.kitfox.svg.SVGElement;
-+import com.kitfox.svg.SVGException;
-+import com.kitfox.svg.SVGLoaderHelper;
-+import com.kitfox.svg.animation.parser.AnimTimeParser;
-+import com.kitfox.svg.animation.parser.ParseException;
-+import com.kitfox.svg.xml.StyleAttribute;
-+import java.io.StringReader;
-+import org.xml.sax.Attributes;
-+import org.xml.sax.SAXException;
-+
-+
-+/**
-+ * @author Mark McKay
-+ * @author <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
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ core/src/com/kitfox/svg/animation/AnimationTimeEval.java	2012-06-17 23:56:57.676545050 +0200
-@@ -0,0 +1,65 @@
-+/*
-+ * AnimateTimeEval.java
-+ *
-+ *  The Salamander Project - 2D and 3D graphics libraries in Java
-+ *  Copyright (C) 2004 Mark McKay
-+ *
-+ *  This library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public
-+ *  License as published by the Free Software Foundation; either
-+ *  version 2.1 of the License, or (at your option) any later version.
-+ *
-+ *  This library is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ *  Lesser General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU Lesser General Public
-+ *  License along with this library; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
-+ *  projects can be found at http://www.kitfox.com
-+ *
-+ *
-+ * Created on September 21, 2004, 1:31 PM
-+ */
-+
-+package com.kitfox.svg.animation;
-+
-+/**
-+ *
-+ * @author  kitfox
-+ */
-+public class AnimationTimeEval
-+{
-+    /**
-+     * Value on [0..1] representing the interpolation value of queried animation
-+     * element, or Double.NaN if element does not provide a valid evalutaion
-+     */
-+    public double interp;
-+    
-+    /**
-+     * Number of completed repetitions
-+     */
-+    public int rep;
-+    
-+    /**
-+     * True if this evaluation is in a frozen state; ie, past the end of the
-+     * track and held in the "freeze" state.
-+     */
-+//    public boolean pastEnd;
-+    
-+    /** Creates a new instance of AnimateTimeEval */
-+    public AnimationTimeEval()
-+    {
-+    }
-+    
-+//    public void set(double interp, int rep, boolean pastEnd)
-+    public void set(double interp, int rep)
-+    {
-+        this.interp = interp;
-+        this.rep = rep;
-+//        this.pastEnd = pastEnd;
-+    }
-+}
-Index: core/src/com/kitfox/svg/animation/Bezier.java
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ core/src/com/kitfox/svg/animation/Bezier.java	2012-06-17 23:56:57.680545050 +0200
-@@ -0,0 +1,201 @@
-+/*
-+ * Bezier.java
-+ *
-+
-+ *  The Salamander Project - 2D and 3D graphics libraries in Java
-+ *  Copyright (C) 2004 Mark McKay
-+ *
-+ *  This library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public
-+ *  License as published by the Free Software Foundation; either
-+ *  version 2.1 of the License, or (at your option) any later version.
-+ *
-+ *  This library is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ *  Lesser General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU Lesser General Public
-+ *  License along with this library; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
-+ *  projects can be found at http://www.kitfox.com
-+ *
-+ * Created on January 14, 2005, 4:08 AM
-+ */
-+
-+package com.kitfox.svg.animation;
-+
-+import java.awt.geom.*;
-+
-+/**
-+ * http://mathworld.wolfram.com/BezierCurve.html
-+ * @author kitfox
-+ */
-+public class Bezier
-+{
-+    double length;
-+    double[] coord;
-+
-+    public Bezier(double sx, double sy, double[] coords, int numCoords)
-+    {
-+        setCoords(sx, sy, coords, numCoords);
-+    }
-+    
-+    public void setCoords(double sx, double sy, double[] coords, int numCoords)
-+    {
-+        coord = new double[numCoords * 2 + 2];
-+        coord[0] = sx;
-+        coord[1] = sy;
-+        for (int i = 0; i < numCoords; i++)
-+        {
-+            coord[i * 2 + 2] = coords[i * 2];
-+            coord[i * 2 + 3] = coords[i * 2 + 1];
-+        }
-+        
-+        calcLength();        
-+    }
-+    
-+    /**
-+     * Retuns aproximation of the length of the bezier
-+     */
-+    public double getLength()
-+    {
-+        return length;
-+    }
-+    
-+    private void calcLength()
-+    {
-+        length = 0;
-+        for (int i = 2; i < coord.length; i += 2)
-+        {
-+            length += lineLength(coord[i - 2], coord[i - 1], coord[i], coord[i + 1]);
-+        }
-+    }
-+    
-+    private double lineLength(double x1, double y1, double x2, double y2)
-+    {
-+        double dx = x2 - x1, dy = y2 - y1;
-+        return Math.sqrt(dx * dx + dy * dy);
-+    }
-+    
-+    public Point2D.Double getFinalPoint(Point2D.Double point)
-+    {
-+        point.x = coord[coord.length - 2];
-+        point.y = coord[coord.length - 1];
-+        return point;
-+    }
-+    
-+    public Point2D.Double eval(double param, Point2D.Double point)
-+    {
-+        point.x = 0;
-+        point.y = 0;
-+        int numKnots = coord.length / 2;
-+        
-+        for (int i = 0; i < numKnots; i++)
-+        {
-+            double scale = bernstein(numKnots - 1, i, param);
-+            point.x += coord[i * 2] * scale;
-+            point.y += coord[i * 2 + 1] * scale;
-+        }
-+        
-+        return point;
-+    }
-+    
-+    /**
-+     * Calculates the bernstein polynomial for evaluating parametric bezier
-+     * @param numKnots - one less than number of knots in this curve hull
-+     * @param knotNo - knot we are evaluating Bernstein for
-+     * @param param - Parametric value we are evaluating at
-+     */
-+    private double bernstein(int numKnots, int knotNo, double param)
-+    {
-+        double iParam = 1 - param;
-+        //Faster evaluation for easy cases:
-+        switch (numKnots)
-+        {
-+            case 0:
-+                return 1;
-+            case 1:
-+            {
-+                switch (knotNo)
-+                {
-+                    case 0:
-+                        return iParam;
-+                    case 1:
-+                        return param;
-+                }
-+                break;
-+            }
-+            case 2:
-+            {
-+                switch (knotNo)
-+                {
-+                    case 0:
-+                        return iParam * iParam;
-+                    case 1:
-+                        return 2 * iParam * param;
-+                    case 2:
-+                        return param * param;
-+                }
-+                break;
-+            }
-+            case 3:
-+            {
-+                switch (knotNo)
-+                {
-+                    case 0:
-+                        return iParam * iParam * iParam;
-+                    case 1:
-+                        return 3 * iParam * iParam * param;
-+                    case 2:
-+                        return 3 * iParam * param * param;
-+                    case 3:
-+                        return param * param * param;
-+                }
-+                break;
-+            }
-+        }
-+        
-+        //If this bezier has more than four points, calculate bernstein the hard way
-+        double retVal = 1;
-+        for (int i = 0; i < knotNo; i++)
-+        {
-+            retVal *= param;
-+        }
-+        for (int i = 0; i < numKnots - knotNo; i++)
-+        {
-+            retVal *= iParam;
-+        }
-+        retVal *= choose(numKnots, knotNo);
-+        
-+        return retVal;
-+    }
-+    
-+    
-+    
-+    private int choose(int num, int denom)
-+    {
-+        int denom2 = num - denom;
-+        if (denom < denom2)
-+        {
-+            int tmp = denom;
-+            denom = denom2;
-+            denom2 = tmp;
-+        }
-+        
-+        int prod = 1;
-+        for (int i = num; i > denom; i--)
-+        {
-+            prod *= num;
-+        }
-+        
-+        for (int i = 2; i <= denom2; i++)
-+        {
-+            prod /= i;
-+        }
-+        
-+        return prod;
-+    }
-+}
-Index: core/src/com/kitfox/svg/animation/SetSmil.java
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ core/src/com/kitfox/svg/animation/SetSmil.java	2012-06-17 23:56:57.680545050 +0200
-@@ -0,0 +1,73 @@
-+/*
-+ * Set.java
-+ *
-+ *  The Salamander Project - 2D and 3D graphics libraries in Java
-+ *  Copyright (C) 2004 Mark McKay
-+ *
-+ *  This library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public
-+ *  License as published by the Free Software Foundation; either
-+ *  version 2.1 of the License, or (at your option) any later version.
-+ *
-+ *  This library is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ *  Lesser General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU Lesser General Public
-+ *  License along with this library; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
-+ *  projects can be found at http://www.kitfox.com
-+ *
-+ * Created on August 15, 2004, 2:51 AM
-+ */
-+
-+package com.kitfox.svg.animation;
-+
-+import com.kitfox.svg.SVGElement;
-+import com.kitfox.svg.SVGException;
-+import com.kitfox.svg.SVGLoaderHelper;
-+import com.kitfox.svg.animation.parser.AnimTimeParser;
-+import com.kitfox.svg.xml.StyleAttribute;
-+import org.xml.sax.Attributes;
-+import org.xml.sax.SAXException;
-+
-+
-+/**
-+ * Set is used to set a textual value; most likely for a style element.
-+ *
-+ * @author Mark McKay
-+ * @author <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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- core.orig/src/com/kitfox/svg/SVGElement.java	2012-05-11 17:03:52.404311564 +0200
-+++ core/src/com/kitfox/svg/SVGElement.java	2012-06-17 23:56:57.732545052 +0200
-@@ -33,6 +33,7 @@
- import java.awt.geom.*;
- 
- import org.xml.sax.*;
-+import com.kitfox.svg.animation.*;
- import com.kitfox.svg.pathcmd.*;
- import com.kitfox.svg.xml.*;
- import java.io.Serializable;
-@@ -100,6 +101,8 @@
+Only in kitfox/svg: animation
+Only in kitfox/svg/app/ant: SVGToImageAntTask.java
+Only in kitfox/svg/app/beans: ProportionalLayoutPanel.form
+Only in kitfox/svg/app/beans: ProportionalLayoutPanel.java
+Only in kitfox/svg/app/beans: SVGPanel.form
+Only in kitfox/svg/app/beans: SVGPanel.java
+Only in kitfox/svg/app/data: HandlerFactory.java
+Only in kitfox/svg/app: MainFrame.form
+Only in kitfox/svg/app: MainFrame.java
+Only in kitfox/svg/app: PlayerDialog.form
+Only in kitfox/svg/app: PlayerDialog.java
+Only in kitfox/svg/app: PlayerThread.java
+Only in kitfox/svg/app: PlayerThreadListener.java
+Only in kitfox/svg/app: SVGPlayer.form
+Only in kitfox/svg/app: SVGPlayer.java
+Only in kitfox/svg/app: SVGViewer.form
+Only in kitfox/svg/app: SVGViewer.java
+Only in kitfox/svg/app: VersionDialog.form
+Only in kitfox/svg/app: VersionDialog.java
+Only in kitfox/svg: SVGDisplayPanel.form
+diff -ur kitfox/svg/SVGElement.java src/com/kitfox/svg/SVGElement.java
+--- kitfox/svg/SVGElement.java	2014-10-30 11:31:46.229650244 +0100
++++ src/com/kitfox/svg/SVGElement.java	2014-10-29 23:30:19.882171106 +0100
+@@ -35,9 +35,6 @@
+  */
+ package com.kitfox.svg;
+ 
+-import com.kitfox.svg.animation.AnimationElement;
+-import com.kitfox.svg.animation.TrackBase;
+-import com.kitfox.svg.animation.TrackManager;
+ import com.kitfox.svg.pathcmd.Arc;
+ import com.kitfox.svg.pathcmd.BuildHistory;
+ import com.kitfox.svg.pathcmd.Cubic;
+@@ -122,10 +119,6 @@
+      * The diagram this element belongs to
       */
- //    protected SVGUniverse universe;
-     
-+    protected final TrackManager trackManager = new TrackManager();
-+
+     protected SVGDiagram diagram;
+-    /**
+-     * Link to the universe we reside in
+-     */
+-    protected final TrackManager trackManager = new TrackManager();
      boolean dirty = true;
  
- //    public static final Matcher adobeId = Pattern.compile("(.*)_1_").matcher("");
-@@ -265,6 +268,46 @@
+     /**
+@@ -305,65 +298,6 @@
          }
      }
-     
-+    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 removeAttribute(String name, int attribType)
+-    {
+-        switch (attribType)
+-        {
+-            case AnimationElement.AT_CSS:
+-                inlineStyles.remove(name);
+-                return;
+-            case AnimationElement.AT_XML:
+-                presAttribs.remove(name);
+-                return;
+-        }
+-    }
+-
+-    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))
+-        {
+-            if (diagram != null)
+-            {
+-                diagram.removeElement(id);
+-                diagram.setElement(value, this);
+-            }
+-            this.id = value;
+-        }
+-
+-        switch (attribType)
+-        {
+-            case AnimationElement.AT_CSS:
+-                inlineStyles.put(name, new StyleAttribute(name, value));
+-                return;
+-            case AnimationElement.AT_XML:
+-                presAttribs.put(name, new StyleAttribute(name, value));
+-                return;
+-        }
+-
+-        throw new SVGElementException(this, "Invalid attribute type " + attribType);
+-    }
+-
+-    public boolean hasAttribute(String name, int attribType) throws SVGElementException
+-    {
+-        switch (attribType)
+-        {
+-            case AnimationElement.AT_CSS:
+-                return inlineStyles.containsKey(name);
+-            case AnimationElement.AT_XML:
+-                return presAttribs.containsKey(name);
+-            case AnimationElement.AT_AUTO:
+-                return inlineStyles.containsKey(name) || presAttribs.containsKey(name);
+-        }
+-
+-        throw new SVGElementException(this, "Invalid attribute type " + attribType);
+-    }
+-
      /**
       * @return a set of Strings that corespond to CSS attributes on this element
       */
-@@ -290,6 +333,12 @@
+@@ -389,12 +323,6 @@
          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)
-@@ -408,6 +457,54 @@
+ 
+     protected void setDiagram(SVGDiagram diagram)
+@@ -529,61 +457,6 @@
          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()))
+-        {
+-            if (diagram != null)
+-            {
+-                diagram.removeElement(this.id);
+-                diagram.setElement(value, this);
+-            }
+-            this.id = value;
+-        }
+-
+-        styAttr.setStringValue(value);
+-    }
+-
+-    public boolean getStyle(StyleAttribute attrib, boolean recursive) throws SVGException
+-    {
+-        return getStyle(attrib, recursive, true);
+-    }
+-    
      /**
-      * Copies the current style into the passed style attribute.  Checks for
-      * inline styles first, then internal and extranal style sheets, and
-@@ -427,6 +524,14 @@
-         
+      * Copies the current style into the passed style attribute. Checks for
+      * inline styles first, then internal and extranal style sheets, and finally
+@@ -595,8 +468,7 @@
+      * style attribute, checks attributes of parents back to root until one
+      * found.
+      */
+-    public boolean getStyle(StyleAttribute attrib, boolean recursive, boolean evalAnimation)
+-            throws SVGException
++    public boolean getStyle(StyleAttribute attrib, boolean recursive) throws SVGException
+     {
+         String styName = attrib.getName();
+ 
+@@ -605,17 +477,6 @@
+ 
          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
+-        if (evalAnimation)
+-        {
+-            TrackBase track = trackManager.getTrack(styName, AnimationElement.AT_CSS);
+-            if (track != null)
+-            {
+-                track.getValue(attrib, diagram.getUniverse().getCurTime());
+-                return true;
+-            }
+-        }
+-
          //Return if we've found a non animated style
-         if (styAttr != null) return true;
-         
-@@ -439,6 +544,14 @@
-         
+         if (styAttr != null)
+         {
+@@ -628,17 +489,6 @@
+ 
          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
+-        if (evalAnimation)
+-        {
+-            TrackBase track = trackManager.getTrack(styName, AnimationElement.AT_XML);
+-            if (track != null)
+-            {
+-                track.getValue(attrib, diagram.getUniverse().getCurTime());
+-                return true;
+-            }
+-        }
+-
          //Return if we've found a presentation attribute instead
-         if (presAttr != null) return true;
-         
-@@ -480,6 +593,14 @@
+         if (presAttr != null)
+         {
+@@ -700,14 +550,6 @@
          //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: core/src/com/kitfox/svg/SVGLoader.java
-===================================================================
---- core.orig/src/com/kitfox/svg/SVGLoader.java	2012-05-11 17:03:52.404311564 +0200
-+++ core/src/com/kitfox/svg/SVGLoader.java	2012-06-17 23:56:57.732545052 +0200
-@@ -33,6 +33,8 @@
+         if (presAttr != null)
+         {
+diff -ur kitfox/svg/SVGLoaderHelper.java src/com/kitfox/svg/SVGLoaderHelper.java
+--- kitfox/svg/SVGLoaderHelper.java	2014-10-29 22:49:38.193473772 +0100
++++ src/com/kitfox/svg/SVGLoaderHelper.java	2014-10-29 22:54:17.671385584 +0100
+@@ -37,9 +37,6 @@
+ package com.kitfox.svg;
+ 
+ import java.net.*;
+-import java.io.*;
+-
+-import com.kitfox.svg.animation.parser.*;
+ 
+ /**
+  * @author Mark McKay
+@@ -58,11 +55,6 @@
+     public final SVGDiagram diagram;
+ 
+     public final URI xmlBase;
+-
+-    /**
+-     * Animate nodes use this to parse their time strings
+-     */
+-    public final AnimTimeParser animTimeParser = new AnimTimeParser(new StringReader(""));
+     
+     /** Creates a new instance of SVGLoaderHelper */
+     public SVGLoaderHelper(URI xmlBase, SVGUniverse universe, SVGDiagram diagram)
+diff -ur kitfox/svg/SVGLoader.java src/com/kitfox/svg/SVGLoader.java
+--- kitfox/svg/SVGLoader.java	2014-10-29 22:49:38.193473772 +0100
++++ src/com/kitfox/svg/SVGLoader.java	2014-10-29 22:53:56.462392128 +0100
+@@ -42,7 +42,6 @@
  import org.xml.sax.*;
  import org.xml.sax.helpers.DefaultHandler;
  
-+import com.kitfox.svg.animation.*;
-+
- /**
-  * @author Mark McKay
-  * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
-@@ -75,6 +77,10 @@
+-import com.kitfox.svg.animation.*;
+ import java.util.logging.Level;
+ import java.util.logging.Logger;
+ 
+@@ -88,10 +87,6 @@
  
          //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);
-@@ -98,6 +104,7 @@
+@@ -115,7 +110,6 @@
          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: core/src/com/kitfox/svg/SVGLoaderHelper.java
-===================================================================
---- core.orig/src/com/kitfox/svg/SVGLoaderHelper.java	2012-05-11 17:03:52.404311564 +0200
-+++ core/src/com/kitfox/svg/SVGLoaderHelper.java	2012-06-17 23:56:57.740545051 +0200
-@@ -28,6 +28,9 @@
- package com.kitfox.svg;
- 
- import java.net.*;
-+import java.io.*;
-+
-+import com.kitfox.svg.animation.parser.*;
- 
- /**
-  * @author Mark McKay
-@@ -47,6 +50,11 @@
- 
-     public final URI xmlBase;
- 
-+    /**
-+     * Animate nodes use this to parse their time strings
-+     */
-+    public final AnimTimeParser animTimeParser = new AnimTimeParser(new StringReader(""));
-+    
-     /** Creates a new instance of SVGLoaderHelper */
-     public SVGLoaderHelper(URI xmlBase, SVGUniverse universe, SVGDiagram diagram)
-     {
-Index: core/src/com/kitfox/svg/app/MainFrame.java
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ core/src/com/kitfox/svg/app/MainFrame.java	2012-06-17 23:56:57.748545052 +0200
-@@ -0,0 +1,134 @@
-+/*
-+ * MainFrame.java
-+ *
-+ * Created on September 6, 2004, 1:19 AM
-+ */
-+
-+package com.kitfox.svg.app;
-+
-+/**
-+ *
-+ * @author  kitfox
-+ */
-+public class MainFrame extends javax.swing.JFrame
-+{
-+    public static final long serialVersionUID = 1;
-+    
-+    /** Creates new form MainFrame */
-+    public MainFrame()
-+    {
-+        initComponents();
-+    }
-+    
-+    /** This method is called from within the constructor to
-+     * initialize the form.
-+     * WARNING: Do NOT modify this code. The content of this method is
-+     * always regenerated by the Form Editor.
-+     */
-+    private void initComponents()//GEN-BEGIN:initComponents
-+    {
-+        jPanel1 = new javax.swing.JPanel();
-+        bn_svgViewer = new javax.swing.JButton();
-+        bn_svgViewer1 = new javax.swing.JButton();
-+        jPanel2 = new javax.swing.JPanel();
-+        bn_quit = new javax.swing.JButton();
-+
-+        setTitle("SVG Salamander - Application Launcher");
-+        addWindowListener(new java.awt.event.WindowAdapter()
-+        {
-+            public void windowClosing(java.awt.event.WindowEvent evt)
-+            {
-+                exitForm(evt);
-+            }
-+        });
-+
-+        jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.Y_AXIS));
-+
-+        bn_svgViewer.setText("SVG Viewer (No animation)");
-+        bn_svgViewer.addActionListener(new java.awt.event.ActionListener()
-+        {
-+            public void actionPerformed(java.awt.event.ActionEvent evt)
-+            {
-+                bn_svgViewerActionPerformed(evt);
-+            }
-+        });
-+
-+        jPanel1.add(bn_svgViewer);
-+
-+        bn_svgViewer1.setText("SVG Player (Animation)");
-+        bn_svgViewer1.addActionListener(new java.awt.event.ActionListener()
-+        {
-+            public void actionPerformed(java.awt.event.ActionEvent evt)
-+            {
-+                bn_svgViewer1ActionPerformed(evt);
-+            }
-+        });
-+
-+        jPanel1.add(bn_svgViewer1);
-+
-+        getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
-+
-+        bn_quit.setText("Quit");
-+        bn_quit.addActionListener(new java.awt.event.ActionListener()
-+        {
-+            public void actionPerformed(java.awt.event.ActionEvent evt)
-+            {
-+                bn_quitActionPerformed(evt);
-+            }
-+        });
-+
-+        jPanel2.add(bn_quit);
-+
-+        getContentPane().add(jPanel2, java.awt.BorderLayout.SOUTH);
-+
-+        pack();
-+    }//GEN-END:initComponents
-+
-+    private void bn_svgViewer1ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_svgViewer1ActionPerformed
-+    {//GEN-HEADEREND:event_bn_svgViewer1ActionPerformed
-+        SVGPlayer.main(null);
-+
-+        close();
-+    }//GEN-LAST:event_bn_svgViewer1ActionPerformed
-+
-+    private void bn_svgViewerActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_svgViewerActionPerformed
-+    {//GEN-HEADEREND:event_bn_svgViewerActionPerformed
-+        SVGViewer.main(null);
-+
-+        close();
-+    }//GEN-LAST:event_bn_svgViewerActionPerformed
-+
-+    private void bn_quitActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_quitActionPerformed
-+    {//GEN-HEADEREND:event_bn_quitActionPerformed
-+        exitForm(null);
-+    }//GEN-LAST:event_bn_quitActionPerformed
-+    
-+    /** Exit the Application */
-+    private void exitForm(java.awt.event.WindowEvent evt)//GEN-FIRST:event_exitForm
-+    {
-+        System.exit(0);
-+    }//GEN-LAST:event_exitForm
-+    
-+    private void close()
-+    {
-+        this.setVisible(false);
-+        this.dispose();
-+    }
-+    
-+    /**
-+     * @param args the command line arguments
-+     */
-+    public static void main(String args[])
-+    {
-+        new MainFrame().setVisible(true);
-+    }
-+    
-+    // Variables declaration - do not modify//GEN-BEGIN:variables
-+    private javax.swing.JButton bn_quit;
-+    private javax.swing.JButton bn_svgViewer;
-+    private javax.swing.JButton bn_svgViewer1;
-+    private javax.swing.JPanel jPanel1;
-+    private javax.swing.JPanel jPanel2;
-+    // End of variables declaration//GEN-END:variables
-+    
-+}
-Index: core/src/com/kitfox/svg/app/PlayerDialog.java
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ core/src/com/kitfox/svg/app/PlayerDialog.java	2012-06-17 23:56:57.748545052 +0200
-@@ -0,0 +1,289 @@
-+/*
-+ * PlayerDialog.java
-+ *
-+ *
-+ *  The Salamander Project - 2D and 3D graphics libraries in Java
-+ *  Copyright (C) 2004 Mark McKay
-+ *
-+ *  This library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public
-+ *  License as published by the Free Software Foundation; either
-+ *  version 2.1 of the License, or (at your option) any later version.
-+ *
-+ *  This library is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ *  Lesser General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU Lesser General Public
-+ *  License along with this library; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
-+ *  projects can be found at http://www.kitfox.com
-+ *
-+ * Created on September 28, 2004, 9:56 PM
-+ */
-+
-+package com.kitfox.svg.app;
-+
-+/**
-+ *
-+ * @author  kitfox
-+ */
-+public class PlayerDialog extends javax.swing.JDialog implements PlayerThreadListener
-+{
-+    public static final long serialVersionUID = 1;
-+    
-+    PlayerThread thread;
-+    
-+    final SVGPlayer parent;
-+    
-+    /** Creates new form PlayerDialog */
-+    public PlayerDialog(SVGPlayer parent)
-+    {
-+        super(parent, false);
-+        initComponents();
-+        
-+        this.parent = parent;
-+        
-+        thread = new PlayerThread();
-+        thread.addListener(this);
-+        
-+        text_timeStepActionPerformed(null);
-+    }
-+    
-+    public void updateTime(double curTime, double timeStep, int playState)
-+    {
-+        if (playState == PlayerThread.PS_STOP) return;
-+        
-+        text_curTime.setText("" + (float)curTime);
-+        parent.updateTime(curTime);
-+//        text_timeStep.setText("" + (int)(1.0 / timeStep));
-+    }
-+    
-+    /** This method is called from within the constructor to
-+     * initialize the form.
-+     * WARNING: Do NOT modify this code. The content of this method is
-+     * always regenerated by the Form Editor.
-+     */
-+    // <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
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ core/src/com/kitfox/svg/app/PlayerThread.java	2012-06-17 23:56:57.748545052 +0200
-@@ -0,0 +1,129 @@
-+/*
-+ * PlayerThread.java
-+ *
-+ *
-+ *  The Salamander Project - 2D and 3D graphics libraries in Java
-+ *  Copyright (C) 2004 Mark McKay
-+ *
-+ *  This library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public
-+ *  License as published by the Free Software Foundation; either
-+ *  version 2.1 of the License, or (at your option) any later version.
-+ *
-+ *  This library is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ *  Lesser General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU Lesser General Public
-+ *  License along with this library; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
-+ *  projects can be found at http://www.kitfox.com
-+ *
-+ * Created on September 28, 2004, 10:07 PM
-+ */
-+
-+
-+package com.kitfox.svg.app;
-+
-+import java.util.*;
-+
-+/**
-+ *
-+ * @author  kitfox
-+ */
-+public class PlayerThread implements Runnable
-+{
-+    HashSet listeners = new HashSet();
-+    
-+    double curTime = 0;
-+    double timeStep = .2;
-+    
-+    public static final int PS_STOP = 0;
-+    public static final int PS_PLAY_FWD = 1;
-+    public static final int PS_PLAY_BACK = 2;
-+    
-+    int playState = PS_STOP;
-+    
-+    Thread thread;
-+    
-+    /** Creates a new instance of PlayerThread */
-+    public PlayerThread()
-+    {
-+        thread = new Thread(this);
-+        thread.start();
-+    }
-+    
-+    public void run()
-+    {
-+        while (thread != null)
-+        {
-+            synchronized (this)
-+            {
-+                switch (playState)
-+                {
-+                    case PS_PLAY_FWD:
-+                        curTime += timeStep;
-+                        break;
-+                    case PS_PLAY_BACK:
-+                        curTime -= timeStep;
-+                        if (curTime < 0) curTime = 0;
-+                        break;
-+                    default:
-+                    case PS_STOP:
-+                        break;
-+                }
-+                
-+                fireTimeUpdateEvent();
-+            }
-+            
-+            try
-+            {
-+                Thread.sleep((long)(timeStep * 1000));
-+            }
-+            catch (Exception e) 
-+            { 
-+                throw new RuntimeException(e); 
-+            }
-+        }
-+    }
-+    
-+    public void exit() { thread = null; }
-+    public synchronized void addListener(PlayerThreadListener listener) 
-+    {
-+        listeners.add(listener); 
-+    }
-+    
-+    public synchronized double getCurTime() { return curTime; }
-+    
-+    public synchronized void setCurTime(double time)
-+    {
-+        curTime = time;
-+    }
-+    
-+    public synchronized double getTimeStep() { return timeStep; }
-+    
-+    public synchronized void setTimeStep(double time)
-+    {
-+        timeStep = time;
-+        if (timeStep < .01) timeStep = .01;
-+    }
-+    
-+    public synchronized int getPlayState() { return playState; }
-+    
-+    public synchronized void setPlayState(int playState)
-+    {
-+        this.playState = playState;
-+    }
-+    
-+    private void fireTimeUpdateEvent()
-+    {
-+        for (Iterator it = listeners.iterator(); it.hasNext();)
-+        {
-+            PlayerThreadListener listener = (PlayerThreadListener)it.next();
-+            listener.updateTime(curTime, timeStep, playState);
-+        }
-+    }
-+}
-Index: core/src/com/kitfox/svg/app/PlayerThreadListener.java
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ core/src/com/kitfox/svg/app/PlayerThreadListener.java	2012-06-17 23:56:57.748545052 +0200
-@@ -0,0 +1,37 @@
-+/*
-+ * PlayerThreadListener.java
-+ *
-+ *
-+ *  The Salamander Project - 2D and 3D graphics libraries in Java
-+ *  Copyright (C) 2004 Mark McKay
-+ *
-+ *  This library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public
-+ *  License as published by the Free Software Foundation; either
-+ *  version 2.1 of the License, or (at your option) any later version.
-+ *
-+ *  This library is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ *  Lesser General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU Lesser General Public
-+ *  License along with this library; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
-+ *  projects can be found at http://www.kitfox.com
-+ *
-+ * Created on September 28, 2004, 10:15 PM
-+ */
-+
-+package com.kitfox.svg.app;
-+
-+/**
-+ *
-+ * @author  kitfox
-+ */
-+public interface PlayerThreadListener
-+{
-+    public void updateTime(double curTime, double timeStep, int playState);
-+}
-Index: core/src/com/kitfox/svg/app/SVGPlayer.java
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ core/src/com/kitfox/svg/app/SVGPlayer.java	2012-06-17 23:56:57.748545052 +0200
-@@ -0,0 +1,436 @@
-+/*
-+ * SVGViewer.java
-+ *
-+ *
-+ *  The Salamander Project - 2D and 3D graphics libraries in Java
-+ *  Copyright (C) 2004 Mark McKay
-+ *
-+ *  This library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public
-+ *  License as published by the Free Software Foundation; either
-+ *  version 2.1 of the License, or (at your option) any later version.
-+ *
-+ *  This library is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ *  Lesser General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU Lesser General Public
-+ *  License along with this library; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
-+ *  projects can be found at http://www.kitfox.com
-+ *
-+ * Created on April 3, 2004, 5:28 PM
-+ */
-+
-+package com.kitfox.svg.app;
-+
-+
-+import com.kitfox.svg.SVGDiagram;
-+import com.kitfox.svg.SVGDisplayPanel;
-+import com.kitfox.svg.SVGElement;
-+import com.kitfox.svg.SVGException;
-+import com.kitfox.svg.SVGUniverse;
-+import java.awt.Color;
-+import java.awt.event.MouseAdapter;
-+import java.awt.event.MouseEvent;
-+import java.awt.geom.Point2D;
-+import java.io.File;
-+import java.io.InputStream;
-+import java.net.URI;
-+import java.net.URL;
-+import java.net.URLEncoder;
-+import java.security.AccessControlException;
-+import java.util.ArrayList;
-+import java.util.List;
-+import java.util.Vector;
-+import java.util.regex.Matcher;
-+import java.util.regex.Pattern;
-+import javax.swing.JFileChooser;
-+import javax.swing.JOptionPane;
-+
-+/**
-+ * @author Mark McKay
-+ * @author <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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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
-===================================================================
---- /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/src/com/kitfox/svg/ClipPath.java
===================================================================
--- /trunk/src/com/kitfox/svg/ClipPath.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/ClipPath.java	(revision 7676)
@@ -131,6 +131,8 @@
      * all attributes with track information.
      *
+     * @param curTime
      * @return - true if this node has changed state as a result of the time
      * update
+     * @throws com.kitfox.svg.SVGException
      */
     public boolean updateTime(double curTime) throws SVGException
@@ -160,4 +162,10 @@
         }
 
+        for (int i = 0; i < children.size(); ++i)
+        {
+            SVGElement ele = (SVGElement) children.get(i);
+            ele.updateTime(curTime);
+        }
+        
         return shapeChange;
     }
Index: /trunk/src/com/kitfox/svg/Group.java
===================================================================
--- /trunk/src/com/kitfox/svg/Group.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/Group.java	(revision 7676)
@@ -160,8 +160,8 @@
         //Do not process offscreen groups
         boolean ignoreClip = diagram.ignoringClipHeuristic();
-        if (!ignoreClip && outsideClip(g))
-        {
-            return;
-        }
+//        if (!ignoreClip && outsideClip(g))
+//        {
+//            return;
+//        }
 
         beginLayer(g);
@@ -271,12 +271,16 @@
                 RenderableElement rendEle = (RenderableElement) ele;
                 Rectangle2D bounds = rendEle.getBoundingBox();
-                if (bounds != null)
+                if (bounds != null && (bounds.getWidth() != 0 || bounds.getHeight() != 0))
                 {
                     if (retRect == null)
                     {
                         retRect = bounds;
-                    } else
+                    }
+                    else
                     {
-                        retRect = retRect.createUnion(bounds);
+                        if (retRect.getWidth() != 0 || retRect.getHeight() != 0)
+                        {
+                            retRect = retRect.createUnion(bounds);
+                        }
                     }
                 }
Index: /trunk/src/com/kitfox/svg/ImageSVG.java
===================================================================
--- /trunk/src/com/kitfox/svg/ImageSVG.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/ImageSVG.java	(revision 7676)
@@ -124,5 +124,5 @@
                     {
                         Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
-                            "Could not parse xlink:href", e);
+                            "Could not parse xlink:href " + src, e);
 //                        e.printStackTrace();
                         imageSrc = null;
Index: /trunk/src/com/kitfox/svg/RadialGradient.java
===================================================================
--- /trunk/src/com/kitfox/svg/RadialGradient.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/RadialGradient.java	(revision 7676)
@@ -121,9 +121,5 @@
         Point2D.Float pt1 = new Point2D.Float(cx, cy);
         Point2D.Float pt2 = new Point2D.Float(fx, fy);
-        if (pt1.equals(pt2))
-        {
-            Color[] colors = getStopColors();
-            paint = colors.length > 0 ? colors[0] : Color.black;
-        } else if (gradientUnits == GU_USER_SPACE_ON_USE)
+        if (gradientUnits == GU_USER_SPACE_ON_USE)
         {
             paint = new com.kitfox.svg.batik.RadialGradientPaint(
Index: /trunk/src/com/kitfox/svg/SVGDiagram.java
===================================================================
--- /trunk/src/com/kitfox/svg/SVGDiagram.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/SVGDiagram.java	(revision 7676)
@@ -103,5 +103,5 @@
     public void render(Graphics2D g) throws SVGException
     {
-        root.render(g);
+        root.renderToViewport(g);
     }
     
Index: /trunk/src/com/kitfox/svg/SVGElement.java
===================================================================
--- /trunk/src/com/kitfox/svg/SVGElement.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/SVGElement.java	(revision 7676)
@@ -588,5 +588,5 @@
     static public AffineTransform parseSingleTransform(String val) throws SVGException
     {
-        final Matcher matchWord = Pattern.compile("[-.\\w]+").matcher("");
+        final Matcher matchWord = Pattern.compile("([a-zA-Z]+|-?\\d+(\\.\\d+)?|-?\\.\\d+)").matcher("");
 
         AffineTransform retXform = new AffineTransform();
Index: /trunk/src/com/kitfox/svg/SVGRoot.java
===================================================================
--- /trunk/src/com/kitfox/svg/SVGRoot.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/SVGRoot.java	(revision 7676)
@@ -44,5 +44,8 @@
 import java.awt.Shape;
 import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
+import java.util.List;
 
 /**
@@ -239,4 +242,25 @@
         clipRect.setRect(xx, yy, ww, hh);
 
+//        if (viewBox == null)
+//        {
+//            viewXform.setToIdentity();
+//        }
+//        else
+//        {
+//            //If viewport window is set, we are drawing to entire viewport
+//            clipRect.setRect(deviceViewport);
+//            
+//            viewXform.setToIdentity();
+//            viewXform.setToTranslation(deviceViewport.x, deviceViewport.y);
+//            viewXform.scale(deviceViewport.width, deviceViewport.height);
+//            viewXform.scale(1 / viewBox.width, 1 / viewBox.height);
+//            viewXform.translate(-viewBox.x, -viewBox.y);
+//        }
+    }
+
+    public void renderToViewport(Graphics2D g) throws SVGException
+    {
+        prepareViewport();
+
         if (viewBox == null)
         {
@@ -245,14 +269,14 @@
         else
         {
-            viewXform.setToTranslation(clipRect.x, clipRect.y);
-            viewXform.scale(clipRect.width, clipRect.height);
+            Rectangle deviceViewport = g.getClipBounds();
+            //If viewport window is set, we are drawing to entire viewport
+            clipRect.setRect(deviceViewport);
+            
+            viewXform.setToIdentity();
+            viewXform.setToTranslation(deviceViewport.x, deviceViewport.y);
+            viewXform.scale(deviceViewport.width, deviceViewport.height);
             viewXform.scale(1 / viewBox.width, 1 / viewBox.height);
             viewXform.translate(-viewBox.x, -viewBox.y);
         }
-    }
-
-    public void render(Graphics2D g) throws SVGException
-    {
-        prepareViewport();
         
         AffineTransform cachedXform = g.getTransform();
@@ -262,4 +286,32 @@
         
         g.setTransform(cachedXform);
+    }
+
+    public void pick(Rectangle2D pickArea, AffineTransform ltw, boolean boundingBox, List retVec) throws SVGException
+    {
+        if (viewXform != null)
+        {
+            ltw = new AffineTransform(ltw);
+            ltw.concatenate(viewXform);
+        }
+        
+        super.pick(pickArea, ltw, boundingBox, retVec);
+    }
+    
+    public void pick(Point2D point, boolean boundingBox, List retVec) throws SVGException
+    {
+        Point2D xPoint = new Point2D.Double(point.getX(), point.getY());
+        if (viewXform != null)
+        {
+            try
+            {
+                viewXform.inverseTransform(point, xPoint);
+            } catch (NoninvertibleTransformException ex)
+            {
+                throw new SVGException(ex);
+            }
+        }
+        
+        super.pick(xPoint, boundingBox, retVec);
     }
 
Index: /trunk/src/com/kitfox/svg/SVGUniverse.java
===================================================================
--- /trunk/src/com/kitfox/svg/SVGUniverse.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/SVGUniverse.java	(revision 7676)
@@ -55,6 +55,5 @@
 import java.net.URISyntaxException;
 import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLStreamHandler;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -389,5 +388,5 @@
             {
                 //Workaround for resources stored in jars loaded by Webstart.
-                //https://bugs.openjdk.java.net/browse/JDK-6753651
+                //http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6753651
                 url = SVGUniverse.class.getResource("xmlBase.getPath()");
             }
@@ -627,43 +626,22 @@
     }
 
-//    public static void main(String argv[])
-//    {
-//        try
-//        {
-//            URL url = new URL("svgSalamander", "localhost", -1, "abc.svg",
-//                    new URLStreamHandler()
-//            {
-//                protected URLConnection openConnection(URL u)
-//                {
-//                    return null;
-//                }
-//            }
-//            );
-////            URL url2 = new URL("svgSalamander", "localhost", -1, "abc.svg");
-//            
-//            //Investigate URI resolution
-//            URI uriA, uriB, uriC, uriD, uriE;
-//            
-//            uriA = new URI("svgSalamander", "/names/mySpecialName", null);
-////            uriA = new URI("http://www.kitfox.com/salamander");
-////            uriA = new URI("svgSalamander://mySpecialName/grape");
-//            System.err.println(uriA.toString());
-//            System.err.println(uriA.getScheme());
-//            
-//            uriB = uriA.resolve("#begin");
-//            System.err.println(uriB.toString());
-//            
-//            uriC = uriA.resolve("tree#boing");
-//            System.err.println(uriC.toString());
-//            
-//            uriC = uriA.resolve("../tree#boing");
-//            System.err.println(uriC.toString());
-//        }
-//        catch (Exception e)
-//        {
-//            Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, 
-//                "Could not parse", e);
-//        }
-//    }
+    /**
+     * Get list of uris of all loaded documents and subdocuments.
+     * @return 
+     */
+    public ArrayList getLoadedDocumentURIs()
+    {
+        return new ArrayList(loadedDocs.keySet());
+    }
+    
+    /**
+     * Remove loaded document from cache.
+     * @param uri 
+     */
+    public void removeDocument(URI uri)
+    {
+        loadedDocs.remove(uri);
+    }
+    
     public boolean isVerbose()
     {
Index: /trunk/src/com/kitfox/svg/ShapeElement.java
===================================================================
--- /trunk/src/com/kitfox/svg/ShapeElement.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/ShapeElement.java	(revision 7676)
@@ -87,5 +87,5 @@
     void pick(Point2D point, boolean boundingBox, List retVec) throws SVGException
     {
-        StyleAttribute styleAttrib = new StyleAttribute();
+//        StyleAttribute styleAttrib = new StyleAttribute();
 //        if (getStyle(styleAttrib.setName("fill")) && getShape().contains(point))
         if ((boundingBox ? getBoundingBox() : getShape()).contains(point))
Index: /trunk/src/com/kitfox/svg/Text.java
===================================================================
--- /trunk/src/com/kitfox/svg/Text.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/Text.java	(revision 7676)
@@ -42,4 +42,5 @@
 import java.awt.geom.AffineTransform;
 import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.util.Iterator;
@@ -209,5 +210,5 @@
         } else
         {
-            fontWeight = TXWE_BOLD;
+            fontWeight = TXWE_NORMAL;
         }
 
@@ -352,5 +353,5 @@
             {
                 AffineTransform at = new AffineTransform();
-                at.translate(-textPath.getBounds2D().getWidth() / 2, 0);
+                at.translate(-textPath.getBounds().getWidth() / 2, 0);
                 textPath.transform(at);
                 break;
@@ -359,5 +360,5 @@
             {
                 AffineTransform at = new AffineTransform();
-                at.translate(-textPath.getBounds2D().getWidth(), 0);
+                at.translate(-textPath.getBounds().getWidth(), 0);
                 textPath.transform(at);
                 break;
@@ -390,5 +391,6 @@
             if (obj instanceof String)
             {
-                String text = (String) obj;
+                String text = (String)obj;
+                text = text.trim();
 
                 Shape textShape = font.createGlyphVector(frc, text).getOutline(cursorX, cursorY);
@@ -415,10 +417,13 @@
 
 
-                Tspan tspan = (Tspan) obj;
-                tspan.setCursorX(cursorX);
-                tspan.setCursorY(cursorY);
-                tspan.addShape(textPath);
-                cursorX = tspan.getCursorX();
-                cursorY = tspan.getCursorY();
+                Tspan tspan = (Tspan)obj;
+                Point2D cursor = new Point2D.Float(cursorX, cursorY);
+//                tspan.setCursorX(cursorX);
+//                tspan.setCursorY(cursorY);
+                tspan.appendToShape(textPath, cursor);
+//                cursorX = tspan.getCursorX();
+//                cursorY = tspan.getCursorY();
+                cursorX = (float)cursor.getX();
+                cursorY = (float)cursor.getY();
 
             }
@@ -430,5 +435,5 @@
             {
                 AffineTransform at = new AffineTransform();
-                at.translate(-textPath.getBounds2D().getWidth() / 2, 0);
+                at.translate(-textPath.getBounds().getWidth() / 2, 0);
                 textPath.transform(at);
                 break;
@@ -437,5 +442,5 @@
             {
                 AffineTransform at = new AffineTransform();
-                at.translate(-textPath.getBounds2D().getWidth(), 0);
+                at.translate(-Math.ceil(textPath.getBounds().getWidth()), 0);
                 textPath.transform(at);
                 break;
Index: /trunk/src/com/kitfox/svg/TransformableElement.java
===================================================================
--- /trunk/src/com/kitfox/svg/TransformableElement.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/TransformableElement.java	(revision 7676)
@@ -71,5 +71,5 @@
     public AffineTransform getXForm()
     {
-        return xform != null ? new AffineTransform(xform) : null;
+        return xform == null ? null : new AffineTransform(xform);
     }
     /*
Index: /trunk/src/com/kitfox/svg/Tspan.java
===================================================================
--- /trunk/src/com/kitfox/svg/Tspan.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/Tspan.java	(revision 7676)
@@ -44,4 +44,5 @@
 import java.awt.geom.AffineTransform;
 import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 
@@ -60,6 +61,6 @@
     float[] rotate = null;
     private String text = "";
-    float cursorX;
-    float cursorY;
+//    float cursorX;
+//    float cursorY;
 
 //    Shape tspanShape;
@@ -76,23 +77,23 @@
     }
 
-    public float getCursorX()
-    {
-        return cursorX;
-    }
-
-    public float getCursorY()
-    {
-        return cursorY;
-    }
-
-    public void setCursorX(float cursorX)
-    {
-        this.cursorX = cursorX;
-    }
-
-    public void setCursorY(float cursorY)
-    {
-        this.cursorY = cursorY;
-    }
+//    public float getCursorX()
+//    {
+//        return cursorX;
+//    }
+//
+//    public float getCursorY()
+//    {
+//        return cursorY;
+//    }
+//
+//    public void setCursorX(float cursorX)
+//    {
+//        this.cursorX = cursorX;
+//    }
+//
+//    public void setCursorY(float cursorY)
+//    {
+//        this.cursorY = cursorY;
+//    }
     /*
      public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent)
@@ -165,21 +166,21 @@
     }
 
-    public void addShape(GeneralPath addShape) throws SVGException
-    {
-        if (x != null)
-        {
-            cursorX = x[0];
-        } else if (dx != null)
-        {
-            cursorX += dx[0];
-        }
-
-        if (y != null)
-        {
-            cursorY = y[0];
-        } else if (dy != null)
-        {
-            cursorY += dy[0];
-        }
+    public void appendToShape(GeneralPath addShape, Point2D cursor) throws SVGException
+    {
+//        if (x != null)
+//        {
+//            cursorX = x[0];
+//        } else if (dx != null)
+//        {
+//            cursorX += dx[0];
+//        }
+//
+//        if (y != null)
+//        {
+//            cursorY = y[0];
+//        } else if (dy != null)
+//        {
+//            cursorY += dy[0];
+//        }
 
         StyleAttribute sty = new StyleAttribute();
@@ -209,5 +210,5 @@
         if (font == null)
         {
-            addShapeSysFont(addShape, font, fontFamily, fontSize, letterSpacing);
+            addShapeSysFont(addShape, font, fontFamily, fontSize, letterSpacing, cursor);
             return;
         }
@@ -221,8 +222,30 @@
         strokeWidthScalar = 1f / fontScale;
 
-        int posPtr = 1;
-
-        for (int i = 0; i < text.length(); i++)
-        {
+        float cursorX = (float)cursor.getX();
+        float cursorY = (float)cursor.getY();
+    
+//        int i = 0;
+
+        String drawText = this.text;
+        drawText = drawText.trim();
+        for (int i = 0; i < drawText.length(); i++)
+        {
+            if (x != null && i < x.length)
+            {
+                cursorX = x[i];
+            } else if (dx != null && i < dx.length)
+            {
+                cursorX += dx[i];
+            }
+            
+            if (y != null && i < y.length)
+            {
+                cursorY = y[i];
+            } else if (dy != null && i < dy.length)
+            {
+                cursorY += dy[i];
+            }
+  //          i++;
+            
             xform.setToIdentity();
             xform.setToTranslation(cursorX, cursorY);
@@ -230,8 +253,8 @@
             if (rotate != null)
             {
-                xform.rotate(rotate[posPtr]);
-            }
-
-            String unicode = text.substring(i, i + 1);
+                xform.rotate(rotate[i]);
+            }
+
+            String unicode = drawText.substring(i, i + 1);
             MissingGlyph glyph = font.getGlyph(unicode);
 
@@ -243,35 +266,48 @@
             }
 
-            if (x != null && posPtr < x.length)
-            {
-                cursorX = x[posPtr];
-                cursorY = y[posPtr++];
-            } else if (dx != null && posPtr < dx.length)
-            {
-                cursorX += dx[posPtr];
-                cursorY += dy[posPtr++];
-            }
-
             cursorX += fontScale * glyph.getHorizAdvX() + letterSpacing;
         }
 
+        //Save final draw point so calling method knows where to begin next
+        // text draw
+        cursor.setLocation(cursorX, cursorY);
         strokeWidthScalar = 1f;
     }
 
     private void addShapeSysFont(GeneralPath addShape, Font font,
-        String fontFamily, float fontSize, float letterSpacing)
-    {
+        String fontFamily, float fontSize, float letterSpacing, Point2D cursor)
+    {
+
         java.awt.Font sysFont = new java.awt.Font(fontFamily, java.awt.Font.PLAIN, (int) fontSize);
 
         FontRenderContext frc = new FontRenderContext(null, true, true);
-        GlyphVector textVector = sysFont.createGlyphVector(frc, text);
+        String renderText = this.text.trim();
 
         AffineTransform xform = new AffineTransform();
 
-        int posPtr = 1;
-        for (int i = 0; i < text.length(); i++)
-        {
+        float cursorX = (float)cursor.getX();
+        float cursorY = (float)cursor.getY();
+//        int i = 0;
+        for (int i = 0; i < renderText.length(); i++)
+        {
+            if (x != null && i < x.length)
+            {
+                cursorX = x[i];
+            } else if (dx != null && i < dx.length)
+            {
+                cursorX += dx[i];
+            }
+
+            if (y != null && i < y.length)
+            {
+                cursorY = y[i];
+            } else if (dy != null && i < dy.length)
+            {
+                cursorY += dy[i];
+            }
+//            i++;
+            
             xform.setToIdentity();
-            xform.setToTranslation(cursorX + i * letterSpacing, cursorY);
+            xform.setToTranslation(cursorX, cursorY);
             if (rotate != null)
             {
@@ -279,25 +315,25 @@
             }
 
-            String unicode = text.substring(i, i + 1);
-            Shape glyphOutline = textVector.getGlyphOutline(i);
-            GlyphMetrics glyphMetrics = textVector.getGlyphMetrics(i);
+//            String unicode = renderText.substring(i, i + 1);
+            GlyphVector textVector = sysFont.createGlyphVector(frc, renderText.substring(i, i + 1));
+            Shape glyphOutline = textVector.getGlyphOutline(0);
+            GlyphMetrics glyphMetrics = textVector.getGlyphMetrics(0);
 
             glyphOutline = xform.createTransformedShape(glyphOutline);
             addShape.append(glyphOutline, false);
 
-            if (x != null && posPtr < x.length)
-            {
-                cursorX = x[posPtr];
-                cursorY = y[posPtr++];
-            } else if (dx != null && posPtr < dx.length)
-            {
-                cursorX += dx[posPtr];
-                cursorY += dy[posPtr++];
-            }
-        }
+
+//            cursorX += fontScale * glyph.getHorizAdvX() + letterSpacing;
+            cursorX += glyphMetrics.getAdvance() + letterSpacing;
+        }
+        
+        cursor.setLocation(cursorX, cursorY);
     }
 
     public void render(Graphics2D g) throws SVGException
     {
+        float cursorX = 0;
+        float cursorY = 0;
+    
         if (x != null)
         {
@@ -385,4 +421,7 @@
     protected void renderSysFont(Graphics2D g, java.awt.Font font) throws SVGException
     {
+        float cursorX = 0;
+        float cursorY = 0;
+    
         int posPtr = 1;
         FontRenderContext frc = g.getFontRenderContext();
Index: /trunk/src/com/kitfox/svg/Use.java
===================================================================
--- /trunk/src/com/kitfox/svg/Use.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/Use.java	(revision 7676)
@@ -124,5 +124,5 @@
         }
 
-        RenderableElement rendEle = (RenderableElement) ref;
+        RenderableElement rendEle = (RenderableElement)ref;
         rendEle.pushParentContext(this);
         rendEle.render(g);
Index: /trunk/src/com/kitfox/svg/app/beans/SVGIcon.java
===================================================================
--- /trunk/src/com/kitfox/svg/app/beans/SVGIcon.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/app/beans/SVGIcon.java	(revision 7676)
@@ -51,6 +51,8 @@
 {
     public static final long serialVersionUID = 1;
-    
-    private PropertyChangeSupport changes = new PropertyChangeSupport(this);
+
+    public static final String PROP_AUTOSIZE = "PROP_AUTOSIZE";
+    
+    private final PropertyChangeSupport changes = new PropertyChangeSupport(this);
     
     SVGUniverse svgUniverse = SVGCache.getSVGUniverse();
@@ -63,11 +65,16 @@
     private boolean clipToViewbox;
     
-//    private String svgPath;
     URI svgURI;
     
-    private boolean scaleToFit;
+//    private boolean scaleToFit;
     AffineTransform scaleXform = new AffineTransform();
-    
-//    Dimension preferredSize = new Dimension(100, 100);
+
+    public static final int AUTOSIZE_NONE = 0;
+    public static final int AUTOSIZE_HORIZ = 1;
+    public static final int AUTOSIZE_VERT = 2;
+    public static final int AUTOSIZE_BESTFIT = 3;
+    public static final int AUTOSIZE_STRETCH = 4;
+    private int autosize = AUTOSIZE_NONE;
+    
     Dimension preferredSize;
     
@@ -92,5 +99,7 @@
     public int getIconHeight()
     {
-        if (scaleToFit && preferredSize != null)
+        if (preferredSize != null &&
+                (autosize == AUTOSIZE_VERT || autosize == AUTOSIZE_STRETCH 
+                || autosize == AUTOSIZE_BESTFIT))
         {
             return preferredSize.height;
@@ -110,5 +119,7 @@
     public int getIconWidth()
     {
-        if (scaleToFit && preferredSize != null)
+        if (preferredSize != null &&
+                (autosize == AUTOSIZE_HORIZ || autosize == AUTOSIZE_STRETCH 
+                || autosize == AUTOSIZE_BESTFIT))
         {
             return preferredSize.width;
@@ -172,6 +183,5 @@
         
         
-        
-        if (!scaleToFit)
+        if (autosize == AUTOSIZE_NONE)
         {
             try
@@ -210,8 +220,32 @@
         
         
-        final Rectangle2D.Double rect = new Rectangle2D.Double();
-        diagram.getViewRect(rect);
-        
-        scaleXform.setToScale(width / rect.width, height / rect.height);
+//        final Rectangle2D.Double rect = new Rectangle2D.Double();
+//        diagram.getViewRect(rect);
+//        
+//        scaleXform.setToScale(width / rect.width, height / rect.height);
+        double diaWidth = diagram.getWidth();
+        double diaHeight = diagram.getHeight();
+        
+        double scaleW = 1;
+        double scaleH = 1;
+        if (autosize == AUTOSIZE_BESTFIT)
+        {
+            scaleW = scaleH = (height / diaHeight < width / diaWidth) 
+                    ? height / diaHeight : width / diaWidth;
+        }
+        else if (autosize == AUTOSIZE_HORIZ)
+        {
+            scaleW = scaleH = width / diaWidth;
+        }
+        else if (autosize == AUTOSIZE_VERT)
+        {
+            scaleW = scaleH = height / diaHeight;
+        }
+        else if (autosize == AUTOSIZE_STRETCH)
+        {
+            scaleW = width / diaWidth;
+            scaleH = height / diaHeight;
+        }
+        scaleXform.setToScale(scaleW, scaleH);
         
         AffineTransform oldXform = g.getTransform();
@@ -315,15 +349,22 @@
      * If this SVG document has a viewbox, if scaleToFit is set, will scale the viewbox to match the
      * preferred size of this icon
+     * @deprecated 
+     * @return 
      */
     public boolean isScaleToFit()
     {
-        return scaleToFit;
-    }
-    
+        return autosize == AUTOSIZE_STRETCH;
+    }
+    
+    /**
+     * @deprecated 
+     * @return 
+     */
     public void setScaleToFit(boolean scaleToFit)
     {
-        boolean old = this.scaleToFit;
-        this.scaleToFit = scaleToFit;
-        changes.firePropertyChange("scaleToFit", old, scaleToFit);
+        setAutosize(AUTOSIZE_STRETCH);
+//        boolean old = this.scaleToFit;
+//        this.scaleToFit = scaleToFit;
+//        firePropertyChange("scaleToFit", old, scaleToFit);
     }
     
@@ -429,4 +470,22 @@
         this.clipToViewbox = clipToViewbox;
     }
-    
+
+    /**
+     * @return the autosize
+     */
+    public int getAutosize()
+    {
+        return autosize;
+    }
+
+    /**
+     * @param autosize the autosize to set
+     */
+    public void setAutosize(int autosize)
+    {
+        int oldAutosize = this.autosize;
+        this.autosize = autosize;
+        changes.firePropertyChange(PROP_AUTOSIZE, oldAutosize, autosize);
+    }
+        
 }
Index: /trunk/src/com/kitfox/svg/pattern/PatternPaintContext.java
===================================================================
--- /trunk/src/com/kitfox/svg/pattern/PatternPaintContext.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/pattern/PatternPaintContext.java	(revision 7676)
@@ -97,5 +97,5 @@
     {
 //System.err.println("" + x + ", " + y + ", " + w + ", " + h);
-        if (buf == null || buf.getWidth() != w || buf.getHeight() != buf.getHeight())
+        if (buf == null || buf.getWidth() != w || buf.getHeight() != h)
         {
             buf = new BufferedImage(w, h, source.getType());
Index: /trunk/src/com/kitfox/svg/xml/ColorTable.java
===================================================================
--- /trunk/src/com/kitfox/svg/xml/ColorTable.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/xml/ColorTable.java	(revision 7676)
@@ -225,4 +225,9 @@
         Color retVal = null;
 
+        if ("".equals(val))
+        {
+            return null;
+        }
+        
         if (val.charAt(0) == '#')
         {
Index: /trunk/src/com/kitfox/svg/xml/cpx/CPXInputStream.java
===================================================================
--- /trunk/src/com/kitfox/svg/xml/cpx/CPXInputStream.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/xml/cpx/CPXInputStream.java	(revision 7676)
@@ -39,10 +39,8 @@
 import com.kitfox.svg.SVGConst;
 import java.io.*;
-import java.util.*;
 import java.util.zip.*;
 import java.security.*;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import javax.crypto.*;
 
 /**
Index: /trunk/src/com/kitfox/svg/xml/cpx/CPXOutputStream.java
===================================================================
--- /trunk/src/com/kitfox/svg/xml/cpx/CPXOutputStream.java	(revision 7675)
+++ /trunk/src/com/kitfox/svg/xml/cpx/CPXOutputStream.java	(revision 7676)
@@ -39,6 +39,4 @@
 import java.io.*;
 import java.util.zip.*;
-import java.security.*;
-import javax.crypto.*;
 
 /**
