Changeset 7676 in josm


Ignore:
Timestamp:
2014-10-30T11:39:47+01:00 (9 years ago)
Author:
stoecker
Message:

update SVG code to current SVN (fix line endings), see #10479

Location:
trunk
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/images/presets/lottery.svg

    r7668 r7676  
    1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    2 <!-- Created with Inkscape (http://www.inkscape.org/) -->
    3 <svg
    4    xmlns:dc="http://purl.org/dc/elements/1.1/"
    5    xmlns:cc="http://web.resource.org/cc/"
    6    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    7    xmlns:svg="http://www.w3.org/2000/svg"
    8    xmlns="http://www.w3.org/2000/svg"
    9    xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
    10    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    11    width="64"
    12    height="64"
    13    id="svg1307"
    14    sodipodi:version="0.32"
    15    inkscape:version="0.43"
    16    version="1.0"
    17    sodipodi:docbase="/tmp/wikinews"
    18    sodipodi:docname="Lotto-v1.svg">
    19   <defs
    20      id="defs1309" />
    21   <sodipodi:namedview
    22      id="base"
    23      pagecolor="#ffffff"
    24      bordercolor="#666666"
    25      borderopacity="1.0"
    26      inkscape:pageopacity="0.0"
    27      inkscape:pageshadow="2"
    28      inkscape:zoom="4"
    29      inkscape:cx="30.25"
    30      inkscape:cy="23.910307"
    31      inkscape:current-layer="layer1"
    32      showgrid="true"
    33      inkscape:document-units="px"
    34      inkscape:grid-bbox="true"
    35      inkscape:window-width="984"
    36      inkscape:window-height="719"
    37      inkscape:window-x="0"
    38      inkscape:window-y="0" />
    39   <metadata
    40      id="metadata1312">
    41     <rdf:RDF>
    42       <cc:Work
    43          rdf:about="">
    44         <dc:format>image/svg+xml</dc:format>
    45         <dc:type
    46            rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
    47       </cc:Work>
    48     </rdf:RDF>
    49   </metadata>
    50   <g
    51      id="layer1"
    52      inkscape:label="Layer 1"
    53      inkscape:groupmode="layer">
    54     <g
    55        id="g6865">
    56       <rect
    57          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    58          y="-1.3614551"
    59          x="10.326274"
    60          height="34"
    61          width="50.067074"
    62          id="rect2216"
    63          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" />
    64       <rect
    65          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    66          y="0.60500801"
    67          x="20.35981"
    68          height="6"
    69          width="6"
    70          id="rect2224"
    71          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" />
    72       <rect
    73          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    74          y="0.60500801"
    75          x="28.35981"
    76          height="6"
    77          width="6"
    78          id="rect2226"
    79          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" />
    80       <rect
    81          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    82          y="0.60500801"
    83          x="36.35981"
    84          height="6"
    85          width="6"
    86          id="rect2228"
    87          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" />
    88       <rect
    89          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    90          y="0.60500801"
    91          x="44.35981"
    92          height="6"
    93          width="6"
    94          id="rect2235"
    95          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" />
    96       <rect
    97          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    98          y="0.60500801"
    99          x="12.359811"
    100          height="6"
    101          width="6"
    102          id="rect2286"
    103          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" />
    104       <rect
    105          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    106          y="0.60500801"
    107          x="52.35981"
    108          height="6"
    109          width="6"
    110          id="rect2288"
    111          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" />
    112       <rect
    113          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    114          y="8.6050081"
    115          x="20.35981"
    116          height="6"
    117          width="6"
    118          id="rect2290"
    119          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" />
    120       <rect
    121          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    122          y="8.6050081"
    123          x="28.35981"
    124          height="6"
    125          width="6"
    126          id="rect2292"
    127          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" />
    128       <rect
    129          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    130          y="8.6050081"
    131          x="36.359814"
    132          height="6"
    133          width="6"
    134          id="rect2294"
    135          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" />
    136       <rect
    137          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    138          y="8.6050081"
    139          x="44.359814"
    140          height="6"
    141          width="6"
    142          id="rect2296"
    143          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" />
    144       <rect
    145          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    146          y="8.6050081"
    147          x="12.359811"
    148          height="6"
    149          width="6"
    150          id="rect2298"
    151          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" />
    152       <rect
    153          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    154          y="8.6050081"
    155          x="52.359814"
    156          height="6"
    157          width="6"
    158          id="rect2300"
    159          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" />
    160       <rect
    161          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    162          y="16.605007"
    163          x="20.359804"
    164          height="6"
    165          width="6"
    166          id="rect2302"
    167          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" />
    168       <rect
    169          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    170          y="16.605007"
    171          x="28.359804"
    172          height="6"
    173          width="6"
    174          id="rect2304"
    175          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" />
    176       <rect
    177          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    178          y="16.605007"
    179          x="36.35981"
    180          height="6"
    181          width="6"
    182          id="rect2306"
    183          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" />
    184       <rect
    185          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    186          y="16.605007"
    187          x="44.35981"
    188          height="6"
    189          width="6"
    190          id="rect2308"
    191          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" />
    192       <rect
    193          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    194          y="16.605007"
    195          x="12.359806"
    196          height="6"
    197          width="6"
    198          id="rect2310"
    199          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" />
    200       <rect
    201          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    202          y="16.605007"
    203          x="52.35981"
    204          height="6"
    205          width="6"
    206          id="rect2312"
    207          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" />
    208       <rect
    209          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    210          y="24.605007"
    211          x="20.35981"
    212          height="6"
    213          width="6"
    214          id="rect2314"
    215          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" />
    216       <rect
    217          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    218          y="24.605007"
    219          x="28.35981"
    220          height="6"
    221          width="6"
    222          id="rect2316"
    223          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" />
    224       <rect
    225          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    226          y="24.605007"
    227          x="36.359818"
    228          height="6"
    229          width="6"
    230          id="rect2318"
    231          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" />
    232       <rect
    233          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    234          y="24.605007"
    235          x="44.359814"
    236          height="6"
    237          width="6"
    238          id="rect2320"
    239          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" />
    240       <rect
    241          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    242          y="24.605007"
    243          x="12.359812"
    244          height="6"
    245          width="6"
    246          id="rect2322"
    247          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" />
    248       <rect
    249          transform="matrix(0.963141,0.268997,-0.268997,0.963141,0,0)"
    250          y="24.605007"
    251          x="52.359814"
    252          height="6"
    253          width="6"
    254          id="rect2324"
    255          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" />
    256       <path
    257          id="path4082"
    258          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"
    259          style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
    260       <path
    261          id="path4084"
    262          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"
    263          style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
    264     </g>
    265     <g
    266        id="g6894"
    267        transform="translate(-0.163838,-37.41383)">
    268       <g
    269          transform="matrix(1.310345,0,0,1.310345,-27.2672,12.59487)"
    270          id="g4137">
    271         <path
    272            sodipodi:type="arc"
    273            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"
    274            id="path1315"
    275            sodipodi:cx="19.710602"
    276            sodipodi:cy="30.85437"
    277            sodipodi:rx="6.805903"
    278            sodipodi:ry="6.805903"
    279            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"
    280            transform="translate(33.5953,16.45153)" />
    281         <text
    282            xml:space="preserve"
    283            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"
    284            x="49.560547"
    285            y="49.453125"
    286            id="text2212"
    287            sodipodi:linespacing="125%"><tspan
    288              sodipodi:role="line"
    289              id="tspan2214"
    290              x="49.560547"
    291              y="49.453125">23</tspan></text>
    292       </g>
    293       <g
    294          transform="matrix(1.310345,0,0,1.310345,-0.646509,6.456979)"
    295          id="g4127">
    296         <path
    297            sodipodi:type="arc"
    298            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"
    299            id="path2202"
    300            sodipodi:cx="19.710602"
    301            sodipodi:cy="30.85437"
    302            sodipodi:rx="6.805903"
    303            sodipodi:ry="6.805903"
    304            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"
    305            transform="translate(2.595301,21.45153)" />
    306         <text
    307            xml:space="preserve"
    308            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"
    309            x="39.434193"
    310            y="58.444778"
    311            id="text2204"
    312            sodipodi:linespacing="100%"
    313            transform="matrix(1.143483,0.274659,-0.403949,0.777495,0,0)"><tspan
    314              sodipodi:role="line"
    315              id="tspan2206"
    316              x="39.434193"
    317              y="58.444778">12</tspan></text>
    318       </g>
    319       <g
    320          transform="matrix(1.310345,0,0,1.310345,4.353479,2.465499)"
    321          id="g4132">
    322         <path
    323            sodipodi:type="arc"
    324            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"
    325            id="path2198"
    326            sodipodi:cx="19.710602"
    327            sodipodi:cy="30.85437"
    328            sodipodi:rx="6.805903"
    329            sodipodi:ry="6.805903"
    330            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"
    331            transform="translate(17.9835,18.83973)" />
    332         <text
    333            xml:space="preserve"
    334            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"
    335            x="45.061573"
    336            y="43.613289"
    337            id="text2208"
    338            sodipodi:linespacing="125%"
    339            transform="scale(0.838717,1.192297)"><tspan
    340              sodipodi:role="line"
    341              id="tspan2210"
    342              x="45.061573"
    343              y="43.613289">42</tspan></text>
    344       </g>
    345     </g>
    346   </g>
    347 </svg>
     1<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>
  • trunk/patches/10trim_svgsalamander.patch

    r5284 r7676  
    1 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.
    2 Index: core/src/com/kitfox/svg/animation/Animate.java
    3 ===================================================================
    4 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    5 +++ core/src/com/kitfox/svg/animation/Animate.java      2012-06-17 23:56:57.664545050 +0200
    6 @@ -0,0 +1,419 @@
    7 +/*
    8 + * Animate.java
    9 + *
    10 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    11 + *  Copyright (C) 2004 Mark McKay
    12 + *
    13 + *  This library is free software; you can redistribute it and/or
    14 + *  modify it under the terms of the GNU Lesser General Public
    15 + *  License as published by the Free Software Foundation; either
    16 + *  version 2.1 of the License, or (at your option) any later version.
    17 + *
    18 + *  This library is distributed in the hope that it will be useful,
    19 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    20 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    21 + *  Lesser General Public License for more details.
    22 + *
    23 + *  You should have received a copy of the GNU Lesser General Public
    24 + *  License along with this library; if not, write to the Free Software
    25 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    26 + *
    27 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    28 + *  projects can be found at http://www.kitfox.com
    29 + *
    30 + * Created on August 15, 2004, 2:51 AM
    31 + */
    32 +
    33 +package com.kitfox.svg.animation;
    34 +
    35 +import com.kitfox.svg.SVGElement;
    36 +import com.kitfox.svg.SVGException;
    37 +import com.kitfox.svg.SVGLoaderHelper;
    38 +import com.kitfox.svg.animation.parser.AnimTimeParser;
    39 +import com.kitfox.svg.xml.ColorTable;
    40 +import com.kitfox.svg.xml.StyleAttribute;
    41 +import com.kitfox.svg.xml.XMLParseUtil;
    42 +import java.awt.Color;
    43 +import java.awt.geom.AffineTransform;
    44 +import java.awt.geom.GeneralPath;
    45 +import java.awt.geom.PathIterator;
    46 +import org.xml.sax.Attributes;
    47 +import org.xml.sax.SAXException;
    48 +
    49 +
    50 +/**
    51 + * Animate is a really annoying morphic tag that could represent a real value,
    52 + * a color or a path
    53 + *
    54 + * @author Mark McKay
    55 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    56 + */
    57 +public class Animate extends AnimateBase implements AnimateColorIface
    58 +{
    59 +//    StyleAttribute retAttrib = new StyleAttribute
    60 +    public static final int DT_REAL = 0;
    61 +    public static final int DT_COLOR = 1;
    62 +    public static final int DT_PATH = 2;
    63 +    int dataType = DT_REAL;
    64 +   
    65 +    protected double fromValue = Double.NaN;
    66 +    protected double toValue = Double.NaN;
    67 +    protected double byValue = Double.NaN;
    68 +    protected double[] valuesValue;
    69 +   
    70 +    protected Color fromColor = null;
    71 +    protected Color toColor = null;
    72 +
    73 +    protected GeneralPath fromPath = null;
    74 +    protected GeneralPath toPath = null;
    75 +
    76 +    /** Creates a new instance of Animate */
    77 +    public Animate()
    78 +    {
    79 +    }
    80 +   
    81 +    public int getDataType()
    82 +    {
    83 +        return dataType;
    84 +    }
    85 +   
    86 +    public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
    87 +    {
    88 +               //Load style string
    89 +        super.loaderStartElement(helper, attrs, parent);
    90 +
    91 +        String strn = attrs.getValue("from");
    92 +        if (strn != null)
    93 +        {
    94 +            if (XMLParseUtil.isDouble(strn))
    95 +            {
    96 +                fromValue = XMLParseUtil.parseDouble(strn);
    97 +            }
    98 +//            else if (attrs.getValue("attributeName").equals("d"))
    99 +//            {
    100 +//                fromPath = this.buildPath(strn, GeneralPath.WIND_EVEN_ODD);
    101 +//                dataType = DT_PATH;
    102 +//            }
    103 +            else
    104 +            {
    105 +                fromColor = ColorTable.parseColor(strn);
    106 +                if (fromColor == null)
    107 +                {
    108 +                    //Try path
    109 +                    fromPath = this.buildPath(strn, GeneralPath.WIND_EVEN_ODD);
    110 +                    dataType = DT_PATH;
    111 +                }
    112 +                else dataType = DT_COLOR;
    113 +            }
    114 +        }
    115 +
    116 +        strn = attrs.getValue("to");
    117 +        if (strn != null)
    118 +        {
    119 +            if (XMLParseUtil.isDouble(strn))
    120 +            {
    121 +                toValue = XMLParseUtil.parseDouble(strn);
    122 +            }
    123 +            else
    124 +            {
    125 +                toColor = ColorTable.parseColor(strn);
    126 +                if (toColor == null)
    127 +                {
    128 +                    //Try path
    129 +                    toPath = this.buildPath(strn, GeneralPath.WIND_EVEN_ODD);
    130 +                    dataType = DT_PATH;
    131 +                }
    132 +                else dataType = DT_COLOR;
    133 +            }
    134 +        }
    135 +
    136 +        strn = attrs.getValue("by");
    137 +        try
    138 +        {
    139 +            if (strn != null) byValue = XMLParseUtil.parseDouble(strn);
    140 +        } catch (Exception e) {}
    141 +
    142 +        strn = attrs.getValue("values");
    143 +        try
    144 +        {
    145 +            if (strn != null) valuesValue = XMLParseUtil.parseDoubleList(strn);
    146 +        } catch (Exception e) {}
    147 +    }
    148 +   
    149 +    /**
    150 +     * Evaluates this animation element for the passed interpolation time.  Interp
    151 +     * must be on [0..1].
    152 +     */
    153 +    public double eval(double interp)
    154 +    {
    155 +        boolean fromExists = !Double.isNaN(fromValue);
    156 +        boolean toExists = !Double.isNaN(toValue);
    157 +        boolean byExists = !Double.isNaN(byValue);
    158 +        boolean valuesExists = valuesValue != null;
    159 +       
    160 +        if (valuesExists)
    161 +        {
    162 +            double sp = interp * valuesValue.length;
    163 +            int ip = (int)sp;
    164 +            double fp = sp - ip;
    165 +           
    166 +            int i0 = ip;
    167 +            int i1 = ip + 1;
    168 +           
    169 +            if (i0 < 0) return valuesValue[0];
    170 +            if (i1 >= valuesValue.length) return valuesValue[valuesValue.length - 1];
    171 +            return valuesValue[i0] * (1 - fp) + valuesValue[i1] * fp;
    172 +        }
    173 +        else if (fromExists && toExists)
    174 +        {
    175 +            return toValue * interp + fromValue * (1.0 - interp);
    176 +        }
    177 +        else if (fromExists && byExists)
    178 +        {
    179 +            return fromValue + byValue * interp;
    180 +        }
    181 +        else if (toExists && byExists)
    182 +        {
    183 +            return toValue - byValue * (1.0 - interp);
    184 +        }
    185 +        else if (byExists)
    186 +        {
    187 +            return byValue * interp;
    188 +        }
    189 
    190 +        //Should not reach this line
    191 +        throw new RuntimeException("Animate tag could not be evalutated - insufficient arguements");
    192 +    }
    193 +
    194 +    public Color evalColor(double interp)
    195 +    {
    196 +        if (fromColor == null && toColor != null)
    197 +        {
    198 +            float[] toCol = new float[3];
    199 +            toColor.getColorComponents(toCol);
    200 +            return new Color(toCol[0] * (float)interp,
    201 +                toCol[1] * (float)interp,
    202 +                toCol[2] * (float)interp);
    203 +        }
    204 +        else if (fromColor != null && toColor != null)
    205 +        {
    206 +            float nInterp = 1 - (float)interp;
    207 +           
    208 +            float[] fromCol = new float[3];
    209 +            float[] toCol = new float[3];
    210 +            fromColor.getColorComponents(fromCol);
    211 +            toColor.getColorComponents(toCol);
    212 +            return new Color(fromCol[0] * nInterp + toCol[0] * (float)interp,
    213 +                fromCol[1] * nInterp + toCol[1] * (float)interp,
    214 +                fromCol[2] * nInterp + toCol[2] * (float)interp);
    215 +        }
    216 +       
    217 +        throw new RuntimeException("Animate tag could not be evalutated - insufficient arguements");
    218 +    }
    219 +
    220 +    public GeneralPath evalPath(double interp)
    221 +    {
    222 +        if (fromPath == null && toPath != null)
    223 +        {
    224 +            PathIterator itTo = toPath.getPathIterator(new AffineTransform());
    225 +           
    226 +            GeneralPath midPath = new GeneralPath();
    227 +            float[] coordsTo = new float[6];
    228 +           
    229 +            for (; !itTo.isDone(); itTo.next())
    230 +            {
    231 +                int segTo = itTo.currentSegment(coordsTo);
    232 +               
    233 +                switch (segTo)
    234 +                {
    235 +                    case PathIterator.SEG_CLOSE:
    236 +                        midPath.closePath();
    237 +                        break;
    238 +                    case PathIterator.SEG_CUBICTO:
    239 +                        midPath.curveTo(
    240 +                                (float)(coordsTo[0] * interp),
    241 +                                (float)(coordsTo[1] * interp),
    242 +                                (float)(coordsTo[2] * interp),
    243 +                                (float)(coordsTo[3] * interp),
    244 +                                (float)(coordsTo[4] * interp),
    245 +                                (float)(coordsTo[5] * interp)
    246 +                                );
    247 +                        break;
    248 +                    case PathIterator.SEG_LINETO:
    249 +                        midPath.lineTo(
    250 +                                (float)(coordsTo[0] * interp),
    251 +                                (float)(coordsTo[1] * interp)
    252 +                                );
    253 +                        break;
    254 +                    case PathIterator.SEG_MOVETO:
    255 +                        midPath.moveTo(
    256 +                                (float)(coordsTo[0] * interp),
    257 +                                (float)(coordsTo[1] * interp)
    258 +                                );
    259 +                        break;
    260 +                    case PathIterator.SEG_QUADTO:
    261 +                        midPath.quadTo(
    262 +                                (float)(coordsTo[0] * interp),
    263 +                                (float)(coordsTo[1] * interp),
    264 +                                (float)(coordsTo[2] * interp),
    265 +                                (float)(coordsTo[3] * interp)
    266 +                                );
    267 +                        break;
    268 +                }
    269 +            }
    270 +           
    271 +            return midPath;
    272 +        }
    273 +        else if (toPath != null)
    274 +        {
    275 +            PathIterator itFrom = fromPath.getPathIterator(new AffineTransform());
    276 +            PathIterator itTo = toPath.getPathIterator(new AffineTransform());
    277 +           
    278 +            GeneralPath midPath = new GeneralPath();
    279 +            float[] coordsFrom = new float[6];
    280 +            float[] coordsTo = new float[6];
    281 +           
    282 +            for (; !itFrom.isDone(); itFrom.next())
    283 +            {
    284 +                int segFrom = itFrom.currentSegment(coordsFrom);
    285 +                int segTo = itTo.currentSegment(coordsTo);
    286 +               
    287 +                if (segFrom != segTo)
    288 +                {
    289 +                    throw new RuntimeException("Path shape mismatch");
    290 +                }
    291 +               
    292 +                switch (segFrom)
    293 +                {
    294 +                    case PathIterator.SEG_CLOSE:
    295 +                        midPath.closePath();
    296 +                        break;
    297 +                    case PathIterator.SEG_CUBICTO:
    298 +                        midPath.curveTo(
    299 +                                (float)(coordsFrom[0] * (1 - interp) + coordsTo[0] * interp),
    300 +                                (float)(coordsFrom[1] * (1 - interp) + coordsTo[1] * interp),
    301 +                                (float)(coordsFrom[2] * (1 - interp) + coordsTo[2] * interp),
    302 +                                (float)(coordsFrom[3] * (1 - interp) + coordsTo[3] * interp),
    303 +                                (float)(coordsFrom[4] * (1 - interp) + coordsTo[4] * interp),
    304 +                                (float)(coordsFrom[5] * (1 - interp) + coordsTo[5] * interp)
    305 +                                );
    306 +                        break;
    307 +                    case PathIterator.SEG_LINETO:
    308 +                        midPath.lineTo(
    309 +                                (float)(coordsFrom[0] * (1 - interp) + coordsTo[0] * interp),
    310 +                                (float)(coordsFrom[1] * (1 - interp) + coordsTo[1] * interp)
    311 +                                );
    312 +                        break;
    313 +                    case PathIterator.SEG_MOVETO:
    314 +                        midPath.moveTo(
    315 +                                (float)(coordsFrom[0] * (1 - interp) + coordsTo[0] * interp),
    316 +                                (float)(coordsFrom[1] * (1 - interp) + coordsTo[1] * interp)
    317 +                                );
    318 +                        break;
    319 +                    case PathIterator.SEG_QUADTO:
    320 +                        midPath.quadTo(
    321 +                                (float)(coordsFrom[0] * (1 - interp) + coordsTo[0] * interp),
    322 +                                (float)(coordsFrom[1] * (1 - interp) + coordsTo[1] * interp),
    323 +                                (float)(coordsFrom[2] * (1 - interp) + coordsTo[2] * interp),
    324 +                                (float)(coordsFrom[3] * (1 - interp) + coordsTo[3] * interp)
    325 +                                );
    326 +                        break;
    327 +                }
    328 +            }
    329 +           
    330 +            return midPath;
    331 +        }
    332 +       
    333 +        throw new RuntimeException("Animate tag could not be evalutated - insufficient arguements");
    334 +    }
    335 +   
    336 +    /**
    337 +     * If this element is being accumulated, detemine the delta to accumulate by
    338 +     */
    339 +    public double repeatSkipSize(int reps)
    340 +    {
    341 +        boolean fromExists = !Double.isNaN(fromValue);
    342 +        boolean toExists = !Double.isNaN(toValue);
    343 +        boolean byExists = !Double.isNaN(byValue);
    344 +       
    345 +        if (fromExists && toExists)
    346 +        {
    347 +            return (toValue - fromValue) * reps;
    348 +        }
    349 +        else if (fromExists && byExists)
    350 +        {
    351 +            return (fromValue + byValue) * reps;
    352 +        }
    353 +        else if (toExists && byExists)
    354 +        {
    355 +            return toValue * reps;
    356 +        }
    357 +        else if (byExists)
    358 +        {
    359 +            return byValue * reps;
    360 +        }
    361 +
    362 +        //Should not reach this line
    363 +        return 0;
    364 +    }
    365 +
    366 +    protected void rebuild(AnimTimeParser animTimeParser) throws SVGException
    367 +    {
    368 +        super.rebuild(animTimeParser);
    369 +
    370 +        StyleAttribute sty = new StyleAttribute();
    371 +
    372 +        if (getPres(sty.setName("from")))
    373 +        {
    374 +            String strn = sty.getStringValue();
    375 +            if (XMLParseUtil.isDouble(strn))
    376 +            {
    377 +                fromValue = XMLParseUtil.parseDouble(strn);
    378 +            }
    379 +            else
    380 +            {
    381 +                fromColor = ColorTable.parseColor(strn);
    382 +                if (fromColor == null)
    383 +                {
    384 +                    //Try path
    385 +                    fromPath = this.buildPath(strn, GeneralPath.WIND_EVEN_ODD);
    386 +                    dataType = DT_PATH;
    387 +                }
    388 +                else dataType = DT_COLOR;
    389 +            }
    390 +        }
    391 +
    392 +        if (getPres(sty.setName("to")))
    393 +        {
    394 +            String strn = sty.getStringValue();
    395 +            if (XMLParseUtil.isDouble(strn))
    396 +            {
    397 +                toValue = XMLParseUtil.parseDouble(strn);
    398 +            }
    399 +            else
    400 +            {
    401 +                toColor = ColorTable.parseColor(strn);
    402 +                if (toColor == null)
    403 +                {
    404 +                    //Try path
    405 +                    toPath = this.buildPath(strn, GeneralPath.WIND_EVEN_ODD);
    406 +                    dataType = DT_PATH;
    407 +                }
    408 +                else dataType = DT_COLOR;
    409 +            }
    410 +        }
    411 +
    412 +        if (getPres(sty.setName("by")))
    413 +        {
    414 +            String strn = sty.getStringValue();
    415 +            if (strn != null) byValue = XMLParseUtil.parseDouble(strn);
    416 +        }
    417 +
    418 +        if (getPres(sty.setName("values")))
    419 +        {
    420 +            String strn = sty.getStringValue();
    421 +            if (strn != null) valuesValue = XMLParseUtil.parseDoubleList(strn);
    422 +        }
    423 +    }
    424 +   
    425 +}
    426 Index: core/src/com/kitfox/svg/animation/AnimateBase.java
    427 ===================================================================
    428 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    429 +++ core/src/com/kitfox/svg/animation/AnimateBase.java  2012-06-17 23:56:57.664545050 +0200
    430 @@ -0,0 +1,133 @@
    431 +/*
    432 + * Animate.java
    433 + *
    434 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    435 + *  Copyright (C) 2004 Mark McKay
    436 + *
    437 + *  This library is free software; you can redistribute it and/or
    438 + *  modify it under the terms of the GNU Lesser General Public
    439 + *  License as published by the Free Software Foundation; either
    440 + *  version 2.1 of the License, or (at your option) any later version.
    441 + *
    442 + *  This library is distributed in the hope that it will be useful,
    443 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    444 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    445 + *  Lesser General Public License for more details.
    446 + *
    447 + *  You should have received a copy of the GNU Lesser General Public
    448 + *  License along with this library; if not, write to the Free Software
    449 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    450 + *
    451 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    452 + *  projects can be found at http://www.kitfox.com
    453 + *
    454 + * Created on August 15, 2004, 2:51 AM
    455 + */
    456 +
    457 +package com.kitfox.svg.animation;
    458 +
    459 +import com.kitfox.svg.SVGElement;
    460 +import com.kitfox.svg.SVGException;
    461 +import com.kitfox.svg.SVGLoaderHelper;
    462 +import com.kitfox.svg.animation.parser.AnimTimeParser;
    463 +import com.kitfox.svg.animation.parser.ParseException;
    464 +import com.kitfox.svg.xml.StyleAttribute;
    465 +import java.io.StringReader;
    466 +import org.xml.sax.Attributes;
    467 +import org.xml.sax.SAXException;
    468 +
    469 +/**
    470 + * @author Mark McKay
    471 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    472 + */
    473 +abstract public class AnimateBase extends AnimationElement
    474 +{
    475 +    protected double repeatCount = Double.NaN;
    476 +    protected TimeBase repeatDur;
    477 +   
    478 +    /** Creates a new instance of Animate */
    479 +    public AnimateBase()
    480 +    {
    481 +    }
    482 +   
    483 +    public void evalParametric(AnimationTimeEval state, double curTime)
    484 +    {
    485 +        evalParametric(state, curTime, repeatCount, repeatDur == null ? Double.NaN : repeatDur.evalTime());
    486 +    }
    487 +   
    488 +    public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
    489 +    {
    490 +               //Load style string
    491 +        super.loaderStartElement(helper, attrs, parent);
    492 +
    493 +        String repeatDurTime = attrs.getValue("repeatDur");
    494 +
    495 +        try
    496 +        {
    497 +            if (repeatDurTime != null)
    498 +            {
    499 +                helper.animTimeParser.ReInit(new StringReader(repeatDurTime));
    500 +                this.repeatDur = helper.animTimeParser.Expr();
    501 +                this.repeatDur.setParentElement(this);
    502 +            }
    503 +        }
    504 +        catch (Exception e)
    505 +        {
    506 +            throw new SAXException(e);
    507 +        }
    508 +       
    509 +        String strn = attrs.getValue("repeatCount");
    510 +        if (strn == null)
    511 +        {
    512 +            repeatCount = 1;
    513 +        }
    514 +        else if ("indefinite".equals(strn))
    515 +        {
    516 +            repeatCount = Double.POSITIVE_INFINITY;
    517 +        }
    518 +        else
    519 +        {
    520 +            try { repeatCount = Double.parseDouble(strn); }
    521 +            catch (Exception e) { repeatCount = Double.NaN; }
    522 +        }
    523 +    }
    524 +
    525 +    protected void rebuild(AnimTimeParser animTimeParser) throws SVGException
    526 +    {
    527 +        super.rebuild(animTimeParser);
    528 +
    529 +        StyleAttribute sty = new StyleAttribute();
    530 +
    531 +        if (getPres(sty.setName("repeatDur")))
    532 +        {
    533 +            String strn = sty.getStringValue();
    534 +            if (strn != null)
    535 +            {
    536 +                animTimeParser.ReInit(new StringReader(strn));
    537 +                try {
    538 +                    this.repeatDur = animTimeParser.Expr();
    539 +                } catch (ParseException ex) {
    540 +                    ex.printStackTrace();
    541 +                }
    542 +            }
    543 +        }
    544 +
    545 +        if (getPres(sty.setName("repeatCount")))
    546 +        {
    547 +            String strn = sty.getStringValue();
    548 +            if (strn == null)
    549 +            {
    550 +                repeatCount = 1;
    551 +            }
    552 +            else if ("indefinite".equals(strn))
    553 +            {
    554 +                repeatCount = Double.POSITIVE_INFINITY;
    555 +            }
    556 +            else
    557 +            {
    558 +                try { repeatCount = Double.parseDouble(strn); }
    559 +                catch (Exception e) { repeatCount = Double.NaN; }
    560 +            }
    561 +        }
    562 +    }
    563 +}
    564 Index: core/src/com/kitfox/svg/animation/AnimateColor.java
    565 ===================================================================
    566 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    567 +++ core/src/com/kitfox/svg/animation/AnimateColor.java 2012-06-17 23:56:57.672545050 +0200
    568 @@ -0,0 +1,105 @@
    569 +/*
    570 + * Animate.java
    571 + *
    572 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    573 + *  Copyright (C) 2004 Mark McKay
    574 + *
    575 + *  This library is free software; you can redistribute it and/or
    576 + *  modify it under the terms of the GNU Lesser General Public
    577 + *  License as published by the Free Software Foundation; either
    578 + *  version 2.1 of the License, or (at your option) any later version.
    579 + *
    580 + *  This library is distributed in the hope that it will be useful,
    581 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    582 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    583 + *  Lesser General Public License for more details.
    584 + *
    585 + *  You should have received a copy of the GNU Lesser General Public
    586 + *  License along with this library; if not, write to the Free Software
    587 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    588 + *
    589 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    590 + *  projects can be found at http://www.kitfox.com
    591 + *
    592 + * Created on August 15, 2004, 2:51 AM
    593 + */
    594 +
    595 +package com.kitfox.svg.animation;
    596 +
    597 +import com.kitfox.svg.SVGElement;
    598 +import com.kitfox.svg.SVGException;
    599 +import com.kitfox.svg.SVGLoaderHelper;
    600 +import com.kitfox.svg.animation.parser.AnimTimeParser;
    601 +import com.kitfox.svg.xml.ColorTable;
    602 +import com.kitfox.svg.xml.StyleAttribute;
    603 +import java.awt.Color;
    604 +import org.xml.sax.Attributes;
    605 +import org.xml.sax.SAXException;
    606 +
    607 +
    608 +/**
    609 + * @author Mark McKay
    610 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    611 + */
    612 +public class AnimateColor extends AnimateBase implements AnimateColorIface
    613 +{
    614 +   
    615 +    protected Color fromValue;
    616 +    protected Color toValue;
    617 +   
    618 +    /** Creates a new instance of Animate */
    619 +    public AnimateColor()
    620 +    {
    621 +    }
    622 +   
    623 +    public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
    624 +    {
    625 +               //Load style string
    626 +        super.loaderStartElement(helper, attrs, parent);
    627 +
    628 +        String strn = attrs.getValue("from");
    629 +        fromValue = ColorTable.parseColor(strn);
    630 +
    631 +        strn = attrs.getValue("to");
    632 +        toValue = ColorTable.parseColor(strn);
    633 +    }
    634 +
    635 +   
    636 +    /**
    637 +     * Evaluates this animation element for the passed interpolation time.  Interp
    638 +     * must be on [0..1].
    639 +     */
    640 +    public Color evalColor(double interp)
    641 +    {
    642 +        int r1 = fromValue.getRed();
    643 +        int g1 = fromValue.getGreen();
    644 +        int b1 = fromValue.getBlue();
    645 +        int r2 = toValue.getRed();
    646 +        int g2 = toValue.getGreen();
    647 +        int b2 = toValue.getBlue();
    648 +        double invInterp = 1.0 - interp;
    649 +       
    650 +        return new Color((int)(r1 * invInterp + r2 * interp),
    651 +            (int)(g1 * invInterp + g2 * interp),
    652 +            (int)(b1 * invInterp + b2 * interp));
    653 +    }
    654 +
    655 +    protected void rebuild(AnimTimeParser animTimeParser) throws SVGException
    656 +    {
    657 +        super.rebuild(animTimeParser);
    658 +
    659 +        StyleAttribute sty = new StyleAttribute();
    660 +
    661 +        if (getPres(sty.setName("from")))
    662 +        {
    663 +            String strn = sty.getStringValue();
    664 +            fromValue = ColorTable.parseColor(strn);
    665 +        }
    666 +
    667 +        if (getPres(sty.setName("to")))
    668 +        {
    669 +            String strn = sty.getStringValue();
    670 +            toValue = ColorTable.parseColor(strn);
    671 +        }
    672 +    }
    673 +}
    674 Index: core/src/com/kitfox/svg/animation/AnimateColorIface.java
    675 ===================================================================
    676 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    677 +++ core/src/com/kitfox/svg/animation/AnimateColorIface.java    2012-06-17 23:56:57.672545050 +0200
    678 @@ -0,0 +1,38 @@
    679 +/*
    680 + * AnimateColorIface.java
    681 + *
    682 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    683 + *  Copyright (C) 2004 Mark McKay
    684 + *
    685 + *  This library is free software; you can redistribute it and/or
    686 + *  modify it under the terms of the GNU Lesser General Public
    687 + *  License as published by the Free Software Foundation; either
    688 + *  version 2.1 of the License, or (at your option) any later version.
    689 + *
    690 + *  This library is distributed in the hope that it will be useful,
    691 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    692 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    693 + *  Lesser General Public License for more details.
    694 + *
    695 + *  You should have received a copy of the GNU Lesser General Public
    696 + *  License along with this library; if not, write to the Free Software
    697 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    698 + *
    699 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    700 + *  projects can be found at http://www.kitfox.com
    701 + *
    702 + * Created on January 16, 2005, 6:24 AM
    703 + */
    704 +
    705 +package com.kitfox.svg.animation;
    706 +
    707 +import java.awt.*;
    708 +
    709 +/**
    710 + *
    711 + * @author kitfox
    712 + */
    713 +public interface AnimateColorIface
    714 +{
    715 +    public Color evalColor(double interp);
    716 +}
    717 Index: core/src/com/kitfox/svg/animation/AnimateMotion.java
    718 ===================================================================
    719 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    720 +++ core/src/com/kitfox/svg/animation/AnimateMotion.java        2012-06-17 23:56:57.672545050 +0200
    721 @@ -0,0 +1,282 @@
    722 +/*
    723 + * Animate.java
    724 + *
    725 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    726 + *  Copyright (C) 2004 Mark McKay
    727 + *
    728 + *  This library is free software; you can redistribute it and/or
    729 + *  modify it under the terms of the GNU Lesser General Public
    730 + *  License as published by the Free Software Foundation; either
    731 + *  version 2.1 of the License, or (at your option) any later version.
    732 + *
    733 + *  This library is distributed in the hope that it will be useful,
    734 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    735 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    736 + *  Lesser General Public License for more details.
    737 + *
    738 + *  You should have received a copy of the GNU Lesser General Public
    739 + *  License along with this library; if not, write to the Free Software
    740 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    741 + *
    742 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    743 + *  projects can be found at http://www.kitfox.com
    744 + *
    745 + * Created on August 15, 2004, 2:51 AM
    746 + */
    747 +
    748 +package com.kitfox.svg.animation;
    749 +
    750 +import com.kitfox.svg.SVGElement;
    751 +import com.kitfox.svg.SVGException;
    752 +import com.kitfox.svg.SVGLoaderHelper;
    753 +import com.kitfox.svg.animation.parser.AnimTimeParser;
    754 +import com.kitfox.svg.xml.StyleAttribute;
    755 +import java.awt.geom.AffineTransform;
    756 +import java.awt.geom.GeneralPath;
    757 +import java.awt.geom.PathIterator;
    758 +import java.awt.geom.Point2D;
    759 +import java.util.ArrayList;
    760 +import java.util.Iterator;
    761 +import java.util.regex.Matcher;
    762 +import java.util.regex.Pattern;
    763 +import org.xml.sax.Attributes;
    764 +import org.xml.sax.SAXException;
    765 +
    766 +
    767 +/**
    768 + * @author Mark McKay
    769 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    770 + */
    771 +public class AnimateMotion extends AnimateXform
    772 +{
    773 +    static final Matcher matchPoint = Pattern.compile("\\s*(\\d+)[^\\d]+(\\d+)\\s*").matcher("");
    774 +   
    775 +//    protected double fromValue;
    776 +//    protected double toValue;
    777 +    GeneralPath path;
    778 +    int rotateType = RT_ANGLE;
    779 +    double rotate;  //Static angle to rotate by
    780 +   
    781 +    public static final int RT_ANGLE = 0;  //Rotate by constant 'rotate' degrees
    782 +    public static final int RT_AUTO = 1;  //Rotate to reflect tangent of position on path
    783 +   
    784 +    final ArrayList bezierSegs = new ArrayList();
    785 +    double curveLength;
    786 +   
    787 +    /** Creates a new instance of Animate */
    788 +    public AnimateMotion()
    789 +    {
    790 +    }
    791 +   
    792 +    public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
    793 +    {
    794 +               //Load style string
    795 +        super.loaderStartElement(helper, attrs, parent);
    796 +       
    797 +        //Motion element implies animating the transform element
    798 +        if (attribName == null)
    799 +        {
    800 +            attribName = "transform";
    801 +            attribType = AT_AUTO;
    802 +            additiveType = AD_SUM;
    803 +        }
    804 +       
    805 +
    806 +        String path = attrs.getValue("path");
    807 +        if (path != null)
    808 +        {
    809 +            this.path = buildPath(path, GeneralPath.WIND_NON_ZERO);
    810 +        }
    811 +       
    812 +        //Now parse rotation style
    813 +        String rotate = attrs.getValue("rotate");
    814 +        if (rotate != null)
    815 +        {
    816 +            if (rotate.equals("auto"))
    817 +            {
    818 +                this.rotateType = RT_AUTO;
    819 +            }
    820 +            else
    821 +            {
    822 +                try { this.rotate = Math.toRadians(Float.parseFloat(rotate)); } catch (Exception e) {}
    823 +            }
    824 +        }
    825 +
    826 +        //Determine path
    827 +        String from = attrs.getValue("from");
    828 +        String to = attrs.getValue("to");
    829 +
    830 +        buildPath(from, to);
    831 +    }
    832 +   
    833 +    protected static void setPoint(Point2D.Float pt, String x, String y)
    834 +    {
    835 +        try { pt.x = Float.parseFloat(x); } catch (Exception e) {};
    836 +       
    837 +        try { pt.y = Float.parseFloat(y); } catch (Exception e) {};
    838 +    }
    839 +
    840 +    private void buildPath(String from, String to)
    841 +    {
    842 +        if (from != null && to != null)
    843 +        {
    844 +            Point2D.Float ptFrom = new Point2D.Float(), ptTo = new Point2D.Float();
    845 +
    846 +            matchPoint.reset(from);
    847 +            if (matchPoint.matches())
    848 +            {
    849 +                setPoint(ptFrom, matchPoint.group(1), matchPoint.group(2));
    850 +            }
    851 +
    852 +            matchPoint.reset(to);
    853 +            if (matchPoint.matches())
    854 +            {
    855 +                setPoint(ptFrom, matchPoint.group(1), matchPoint.group(2));
    856 +            }
    857 +
    858 +            if (ptFrom != null && ptTo != null)
    859 +            {
    860 +                path = new GeneralPath();
    861 +                path.moveTo(ptFrom.x, ptFrom.y);
    862 +                path.lineTo(ptTo.x, ptTo.y);
    863 +            }
    864 +        }
    865 +
    866 +        paramaterizePath();
    867 +    }
    868 +   
    869 +    private void paramaterizePath()
    870 +    {
    871 +        bezierSegs.clear();
    872 +        curveLength = 0;
    873 +       
    874 +        double[] coords = new double[6];
    875 +        double sx = 0, sy = 0;
    876 +       
    877 +        for (PathIterator pathIt = path.getPathIterator(new AffineTransform()); !pathIt.isDone(); pathIt.next())
    878 +        {
    879 +            Bezier bezier = null;
    880 +                   
    881 +            int segType = pathIt.currentSegment(coords);
    882 +           
    883 +            switch (segType)
    884 +            {
    885 +                case PathIterator.SEG_LINETO:
    886 +                {
    887 +                    bezier = new Bezier(sx, sy, coords, 1);
    888 +                    sx = coords[0];
    889 +                    sy = coords[1];
    890 +                    break;
    891 +                }
    892 +                case PathIterator.SEG_QUADTO:
    893 +                {
    894 +                    bezier = new Bezier(sx, sy, coords, 2);
    895 +                    sx = coords[2];
    896 +                    sy = coords[3];
    897 +                    break;
    898 +                }
    899 +                case PathIterator.SEG_CUBICTO:
    900 +                {
    901 +                    bezier = new Bezier(sx, sy, coords, 3);
    902 +                    sx = coords[4];
    903 +                    sy = coords[5];
    904 +                    break;
    905 +                }
    906 +                case PathIterator.SEG_MOVETO:
    907 +                {
    908 +                    sx = coords[0];
    909 +                    sy = coords[1];
    910 +                    break;
    911 +                }
    912 +                case PathIterator.SEG_CLOSE:
    913 +                    //Do nothing
    914 +                    break;
    915 +               
    916 +            }
    917 +
    918 +            if (bezier != null)
    919 +            {
    920 +                bezierSegs.add(bezier);
    921 +                curveLength += bezier.getLength();
    922 +            }
    923 +        }
    924 +    }
    925 +   
    926 +    /**
    927 +     * Evaluates this animation element for the passed interpolation time.  Interp
    928 +     * must be on [0..1].
    929 +     */
    930 +    public AffineTransform eval(AffineTransform xform, double interp)
    931 +    {
    932 +        Point2D.Double point = new Point2D.Double();
    933 +       
    934 +        if (interp >= 1)
    935 +        {
    936 +            Bezier last = (Bezier)bezierSegs.get(bezierSegs.size() - 1);
    937 +            last.getFinalPoint(point);
    938 +            xform.setToTranslation(point.x, point.y);
    939 +            return xform;
    940 +        }
    941 +       
    942 +        double curLength = curveLength * interp;
    943 +        for (Iterator it = bezierSegs.iterator(); it.hasNext();)
    944 +        {
    945 +            Bezier bez = (Bezier)it.next();
    946 +           
    947 +            double bezLength = bez.getLength();
    948 +            if (curLength < bezLength)
    949 +            {
    950 +                double param = curLength / bezLength;
    951 +                bez.eval(param, point);
    952 +                break;
    953 +            }
    954 +           
    955 +            curLength -= bezLength;
    956 +        }
    957 +       
    958 +        xform.setToTranslation(point.x, point.y);
    959 +       
    960 +        return xform;
    961 +    }
    962 +   
    963 +
    964 +    protected void rebuild(AnimTimeParser animTimeParser) throws SVGException
    965 +    {
    966 +        super.rebuild(animTimeParser);
    967 +
    968 +        StyleAttribute sty = new StyleAttribute();
    969 +
    970 +        if (getPres(sty.setName("path")))
    971 +        {
    972 +            String strn = sty.getStringValue();
    973 +            this.path = buildPath(strn, GeneralPath.WIND_NON_ZERO);
    974 +        }
    975 +
    976 +        if (getPres(sty.setName("rotate")))
    977 +        {
    978 +            String strn = sty.getStringValue();
    979 +            if (strn.equals("auto"))
    980 +            {
    981 +                this.rotateType = RT_AUTO;
    982 +            }
    983 +            else
    984 +            {
    985 +                try { this.rotate = Math.toRadians(Float.parseFloat(strn)); } catch (Exception e) {}
    986 +            }
    987 +        }
    988 +
    989 +        String from = null;
    990 +        if (getPres(sty.setName("from")))
    991 +        {
    992 +            from = sty.getStringValue();
    993 +        }
    994 +
    995 +        String to = null;
    996 +        if (getPres(sty.setName("to")))
    997 +        {
    998 +            to = sty.getStringValue();
    999 +        }
    1000 +       
    1001 +        buildPath(from, to);
    1002 +    }
    1003 +}
    1004 Index: core/src/com/kitfox/svg/animation/AnimateTransform.java
    1005 ===================================================================
    1006 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    1007 +++ core/src/com/kitfox/svg/animation/AnimateTransform.java     2012-06-17 23:56:57.676545050 +0200
    1008 @@ -0,0 +1,302 @@
    1009 +/*
    1010 + * Animate.java
    1011 + *
    1012 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    1013 + *  Copyright (C) 2004 Mark McKay
    1014 + *
    1015 + *  This library is free software; you can redistribute it and/or
    1016 + *  modify it under the terms of the GNU Lesser General Public
    1017 + *  License as published by the Free Software Foundation; either
    1018 + *  version 2.1 of the License, or (at your option) any later version.
    1019 + *
    1020 + *  This library is distributed in the hope that it will be useful,
    1021 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    1022 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    1023 + *  Lesser General Public License for more details.
    1024 + *
    1025 + *  You should have received a copy of the GNU Lesser General Public
    1026 + *  License along with this library; if not, write to the Free Software
    1027 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    1028 + *
    1029 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    1030 + *  projects can be found at http://www.kitfox.com
    1031 + *
    1032 + * Created on August 15, 2004, 2:51 AM
    1033 + */
    1034 +
    1035 +package com.kitfox.svg.animation;
    1036 +
    1037 +import com.kitfox.svg.SVGElement;
    1038 +import com.kitfox.svg.SVGException;
    1039 +import com.kitfox.svg.SVGLoaderHelper;
    1040 +import com.kitfox.svg.animation.parser.AnimTimeParser;
    1041 +import com.kitfox.svg.xml.StyleAttribute;
    1042 +import com.kitfox.svg.xml.XMLParseUtil;
    1043 +import java.awt.geom.AffineTransform;
    1044 +import java.util.regex.Pattern;
    1045 +import org.xml.sax.Attributes;
    1046 +import org.xml.sax.SAXException;
    1047 +
    1048 +
    1049 +/**
    1050 + * @author Mark McKay
    1051 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    1052 + */
    1053 +public class AnimateTransform extends AnimateXform
    1054 +{
    1055 +//    protected AffineTransform fromValue;
    1056 +//    protected AffineTransform toValue;
    1057 +//    protected double[] fromValue;  //Transform parameters
    1058 +//    protected double[] toValue;
    1059 +    protected double[][] values;
    1060 +    protected double[] keyTimes;
    1061 +
    1062 +    public static final int AT_REPLACE = 0;
    1063 +    public static final int AT_SUM = 1;
    1064 +
    1065 +    protected int additive = AT_REPLACE;
    1066 +
    1067 +    public static final int TR_TRANSLATE = 0;
    1068 +    public static final int TR_ROTATE = 1;
    1069 +    public static final int TR_SCALE = 2;
    1070 +    public static final int TR_SKEWY = 3;
    1071 +    public static final int TR_SKEWX = 4;
    1072 +    public static final int TR_INVALID = 5;
    1073 +
    1074 +    protected int xformType = TR_INVALID;
    1075 +
    1076 +    /** Creates a new instance of Animate */
    1077 +    public AnimateTransform()
    1078 +    {
    1079 +    }
    1080 +
    1081 +    public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
    1082 +    {
    1083 +               //Load style string
    1084 +        super.loaderStartElement(helper, attrs, parent);
    1085 +
    1086 +        //Type of matrix of transform.  Should be one of the known names used to
    1087 +        // define matrix transforms
    1088 +        // valid types: translate, scale, rotate, skewX, skewY
    1089 +        // 'matrix' not valid for animation
    1090 +        String type = attrs.getValue("type").toLowerCase();
    1091 +        if (type.equals("translate")) xformType = TR_TRANSLATE;
    1092 +        if (type.equals("rotate")) xformType = TR_ROTATE;
    1093 +        if (type.equals("scale")) xformType = TR_SCALE;
    1094 +        if (type.equals("skewx")) xformType = TR_SKEWX;
    1095 +        if (type.equals("skewy")) xformType = TR_SKEWY;
    1096 +
    1097 +        String fromStrn = attrs.getValue("from");
    1098 +        String toStrn = attrs.getValue("to");
    1099 +        if (fromStrn != null && toStrn != null)
    1100 +        {
    1101 +            //fromValue = parseSingleTransform(type + "(" + strn + ")");
    1102 +            double[] fromValue = XMLParseUtil.parseDoubleList(fromStrn);
    1103 +            fromValue = validate(fromValue);
    1104 +
    1105 +    //        toValue = parseSingleTransform(type + "(" + strn + ")");
    1106 +            double[] toValue = XMLParseUtil.parseDoubleList(toStrn);
    1107 +            toValue = validate(toValue);
    1108 +           
    1109 +            values = new double[][]{fromValue, toValue};
    1110 +            keyTimes = new double[]{0, 1};
    1111 +        }
    1112 +
    1113 +        String keyTimeStrn = attrs.getValue("keyTimes");
    1114 +        String valuesStrn = attrs.getValue("values");
    1115 +        if (keyTimeStrn != null && valuesStrn != null)
    1116 +        {
    1117 +            keyTimes = XMLParseUtil.parseDoubleList(keyTimeStrn);
    1118 +           
    1119 +            String[] valueList = Pattern.compile(";").split(valuesStrn);
    1120 +            values = new double[valueList.length][];
    1121 +            for (int i = 0; i < valueList.length; i++)
    1122 +            {
    1123 +                double[] list = XMLParseUtil.parseDoubleList(valueList[i]);
    1124 +                values[i] = validate(list);
    1125 +            }
    1126 +        }
    1127 +       
    1128 +        //Check our additive state
    1129 +        String additive = attrs.getValue("additive");
    1130 +        if (additive != null)
    1131 +        {
    1132 +            if (additive.equals("sum")) this.additive = AT_SUM;
    1133 +        }
    1134 +    }
    1135 +
    1136 +    /**
    1137 +     * Check list size against current xform type and ensure list
    1138 +     * is expanded to a standard list size
    1139 +     */
    1140 +    private double[] validate(double[] paramList)
    1141 +    {
    1142 +        switch (xformType)
    1143 +        {
    1144 +            case TR_SCALE:
    1145 +            {
    1146 +                if (paramList == null)
    1147 +                {
    1148 +                    paramList = new double[]{1, 1};
    1149 +                }
    1150 +                else if (paramList.length == 1)
    1151 +                {
    1152 +                    paramList = new double[]{paramList[0], paramList[0]};
    1153 +                   
    1154 +//                    double[] tmp = paramList;
    1155 +//                    paramList = new double[2];
    1156 +//                    paramList[0] = paramList[1] = tmp[0];
    1157 +                }
    1158 +            }
    1159 +        }
    1160 +
    1161 +        return paramList;
    1162 +    }
    1163 +
    1164 +    /**
    1165 +     * Evaluates this animation element for the passed interpolation time.  Interp
    1166 +     * must be on [0..1].
    1167 +     */
    1168 +    public AffineTransform eval(AffineTransform xform, double interp)
    1169 +    {
    1170 +        int idx = 0;
    1171 +        for (; idx < keyTimes.length - 1; idx++)
    1172 +        {
    1173 +            if (interp >= keyTimes[idx])
    1174 +            {
    1175 +                idx--;
    1176 +                if (idx < 0) idx = 0;
    1177 +                break;
    1178 +            }
    1179 +        }
    1180 +       
    1181 +        double spanStartTime = keyTimes[idx];
    1182 +        double spanEndTime = keyTimes[idx + 1];
    1183 +//        double span = spanStartTime - spanEndTime;
    1184 +       
    1185 +        interp = (interp - spanStartTime) / (spanEndTime - spanStartTime);
    1186 +        double[] fromValue = values[idx];
    1187 +        double[] toValue = values[idx + 1];
    1188 +       
    1189 +        switch (xformType)
    1190 +        {
    1191 +            case TR_TRANSLATE:
    1192 +            {
    1193 +                double x = (1.0 - interp) * fromValue[0] + interp * toValue[0];
    1194 +                double y = (1.0 - interp) * fromValue[1] + interp * toValue[1];
    1195 +                xform.setToTranslation(x, y);
    1196 +                break;
    1197 +            }
    1198 +            case TR_ROTATE:
    1199 +            {
    1200 +                double x1 = fromValue.length == 3 ? fromValue[1] : 0;
    1201 +                double y1 = fromValue.length == 3 ? fromValue[2] : 0;
    1202 +                double x2 = toValue.length == 3 ? toValue[1] : 0;
    1203 +                double y2 = toValue.length == 3 ? toValue[2] : 0;
    1204 +               
    1205 +                double theta = (1.0 - interp) * fromValue[0] + interp * toValue[0];
    1206 +                double x = (1.0 - interp) * x1 + interp * x2;
    1207 +                double y = (1.0 - interp) * y1 + interp * y2;
    1208 +                xform.setToRotation(Math.toRadians(theta), x, y);
    1209 +                break;
    1210 +            }
    1211 +            case TR_SCALE:
    1212 +            {
    1213 +                double x = (1.0 - interp) * fromValue[0] + interp * toValue[0];
    1214 +                double y = (1.0 - interp) * fromValue[1] + interp * toValue[1];
    1215 +                xform.setToScale(x, y);
    1216 +                break;
    1217 +            }
    1218 +            case TR_SKEWX:
    1219 +            {
    1220 +                double x = (1.0 - interp) * fromValue[0] + interp * toValue[0];
    1221 +                xform.setToShear(Math.toRadians(x), 0.0);
    1222 +                break;
    1223 +            }
    1224 +            case TR_SKEWY:
    1225 +            {
    1226 +                double y = (1.0 - interp) * fromValue[0] + interp * toValue[0];
    1227 +                xform.setToShear(0.0, Math.toRadians(y));
    1228 +                break;
    1229 +            }
    1230 +            default:
    1231 +                xform.setToIdentity();
    1232 +                break;
    1233 +        }
    1234 +
    1235 +        return xform;
    1236 +    }
    1237 +
    1238 +    protected void rebuild(AnimTimeParser animTimeParser) throws SVGException
    1239 +    {
    1240 +        super.rebuild(animTimeParser);
    1241 +
    1242 +        StyleAttribute sty = new StyleAttribute();
    1243 +
    1244 +        if (getPres(sty.setName("type")))
    1245 +        {
    1246 +            String strn = sty.getStringValue().toLowerCase();
    1247 +            if (strn.equals("translate")) xformType = TR_TRANSLATE;
    1248 +            if (strn.equals("rotate")) xformType = TR_ROTATE;
    1249 +            if (strn.equals("scale")) xformType = TR_SCALE;
    1250 +            if (strn.equals("skewx")) xformType = TR_SKEWX;
    1251 +            if (strn.equals("skewy")) xformType = TR_SKEWY;
    1252 +        }
    1253 +
    1254 +        String fromStrn = null;
    1255 +        if (getPres(sty.setName("from")))
    1256 +        {
    1257 +            fromStrn = sty.getStringValue();
    1258 +        }
    1259 +
    1260 +        String toStrn = null;
    1261 +        if (getPres(sty.setName("to")))
    1262 +        {
    1263 +            toStrn = sty.getStringValue();
    1264 +        }
    1265 +
    1266 +        if (fromStrn != null && toStrn != null)
    1267 +        {
    1268 +            double[] fromValue = XMLParseUtil.parseDoubleList(fromStrn);
    1269 +            fromValue = validate(fromValue);
    1270 +
    1271 +            double[] toValue = XMLParseUtil.parseDoubleList(toStrn);
    1272 +            toValue = validate(toValue);
    1273 +
    1274 +            values = new double[][]{fromValue, toValue};
    1275 +        }
    1276 +
    1277 +        String keyTimeStrn = null;
    1278 +        if (getPres(sty.setName("keyTimes")))
    1279 +        {
    1280 +            keyTimeStrn = sty.getStringValue();
    1281 +        }
    1282 +
    1283 +        String valuesStrn = null;
    1284 +        if (getPres(sty.setName("values")))
    1285 +        {
    1286 +            valuesStrn = sty.getStringValue();
    1287 +        }
    1288 +
    1289 +        if (keyTimeStrn != null && valuesStrn != null)
    1290 +        {
    1291 +            keyTimes = XMLParseUtil.parseDoubleList(keyTimeStrn);
    1292 +
    1293 +            String[] valueList = Pattern.compile(";").split(valuesStrn);
    1294 +            values = new double[valueList.length][];
    1295 +            for (int i = 0; i < valueList.length; i++)
    1296 +            {
    1297 +                double[] list = XMLParseUtil.parseDoubleList(valueList[i]);
    1298 +                values[i] = validate(list);
    1299 +            }
    1300 +        }
    1301 +
    1302 +        //Check our additive state
    1303 +
    1304 +        if (getPres(sty.setName("additive")))
    1305 +        {
    1306 +            String strn = sty.getStringValue().toLowerCase();
    1307 +            if (strn.equals("sum")) this.additive = AT_SUM;
    1308 +        }
    1309 +    }
    1310 +}
    1311 Index: core/src/com/kitfox/svg/animation/AnimateXform.java
    1312 ===================================================================
    1313 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    1314 +++ core/src/com/kitfox/svg/animation/AnimateXform.java 2012-06-17 23:56:57.676545050 +0200
    1315 @@ -0,0 +1,54 @@
    1316 +/*
    1317 + * AnimateXform.java
    1318 + *
    1319 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    1320 + *  Copyright (C) 2004 Mark McKay
    1321 + *
    1322 + *  This library is free software; you can redistribute it and/or
    1323 + *  modify it under the terms of the GNU Lesser General Public
    1324 + *  License as published by the Free Software Foundation; either
    1325 + *  version 2.1 of the License, or (at your option) any later version.
    1326 + *
    1327 + *  This library is distributed in the hope that it will be useful,
    1328 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    1329 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    1330 + *  Lesser General Public License for more details.
    1331 + *
    1332 + *  You should have received a copy of the GNU Lesser General Public
    1333 + *  License along with this library; if not, write to the Free Software
    1334 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    1335 + *
    1336 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    1337 + *  projects can be found at http://www.kitfox.com
    1338 + *
    1339 + * Created on January 14, 2005, 6:46 AM
    1340 + */
    1341 +
    1342 +package com.kitfox.svg.animation;
    1343 +
    1344 +import com.kitfox.svg.SVGElement;
    1345 +import com.kitfox.svg.SVGLoaderHelper;
    1346 +import java.awt.geom.AffineTransform;
    1347 +import org.xml.sax.Attributes;
    1348 +import org.xml.sax.SAXException;
    1349 +
    1350 +
    1351 +
    1352 +/**
    1353 + *
    1354 + * @author kitfox
    1355 + */
    1356 +abstract public class AnimateXform extends AnimateBase
    1357 +{
    1358 +    public AnimateXform()
    1359 +    {
    1360 +    }
    1361 +   
    1362 +    public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
    1363 +    {
    1364 +        super.loaderStartElement(helper, attrs, parent);
    1365 +    }
    1366 +   
    1367 +    abstract public AffineTransform eval(AffineTransform xform, double interp);
    1368 +   
    1369 +}
    1370 Index: core/src/com/kitfox/svg/animation/AnimationElement.java
    1371 ===================================================================
    1372 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    1373 +++ core/src/com/kitfox/svg/animation/AnimationElement.java     2012-06-17 23:56:57.676545050 +0200
    1374 @@ -0,0 +1,414 @@
    1375 +/*
    1376 + * AnimateEle.java
    1377 + *
    1378 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    1379 + *  Copyright (C) 2004 Mark McKay
    1380 + *
    1381 + *  This library is free software; you can redistribute it and/or
    1382 + *  modify it under the terms of the GNU Lesser General Public
    1383 + *  License as published by the Free Software Foundation; either
    1384 + *  version 2.1 of the License, or (at your option) any later version.
    1385 + *
    1386 + *  This library is distributed in the hope that it will be useful,
    1387 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    1388 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    1389 + *  Lesser General Public License for more details.
    1390 + *
    1391 + *  You should have received a copy of the GNU Lesser General Public
    1392 + *  License along with this library; if not, write to the Free Software
    1393 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    1394 + *
    1395 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    1396 + *  projects can be found at http://www.kitfox.com
    1397 + *
    1398 + * Created on August 15, 2004, 2:52 AM
    1399 + */
    1400 +
    1401 +package com.kitfox.svg.animation;
    1402 +
    1403 +import com.kitfox.svg.SVGElement;
    1404 +import com.kitfox.svg.SVGException;
    1405 +import com.kitfox.svg.SVGLoaderHelper;
    1406 +import com.kitfox.svg.animation.parser.AnimTimeParser;
    1407 +import com.kitfox.svg.animation.parser.ParseException;
    1408 +import com.kitfox.svg.xml.StyleAttribute;
    1409 +import java.io.StringReader;
    1410 +import org.xml.sax.Attributes;
    1411 +import org.xml.sax.SAXException;
    1412 +
    1413 +
    1414 +/**
    1415 + * @author Mark McKay
    1416 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    1417 + */
    1418 +public abstract class AnimationElement extends SVGElement
    1419 +{
    1420 +    protected String attribName;
    1421 +//    protected String attribType;
    1422 +    protected int attribType = AT_AUTO;
    1423 +
    1424 +    public static final int AT_CSS = 0;
    1425 +    public static final int AT_XML = 1;
    1426 +    public static final int AT_AUTO = 2;  //Check CSS first, then XML
    1427 +
    1428 +    protected TimeBase beginTime;
    1429 +    protected TimeBase durTime;
    1430 +    protected TimeBase endTime;
    1431 +    protected int fillType = FT_AUTO;
    1432 +
    1433 +    /** <a href="http://www.w3.org/TR/smil20/smil-timing.html#adef-fill">More about the <b>fill</b> attribute</a> */
    1434 +    public static final int FT_REMOVE = 0;
    1435 +    public static final int FT_FREEZE = 1;
    1436 +    public static final int FT_HOLD = 2;
    1437 +    public static final int FT_TRANSITION = 3;
    1438 +    public static final int FT_AUTO = 4;
    1439 +    public static final int FT_DEFAULT = 5;
    1440 +
    1441 +    /** Additive state of track */
    1442 +    public static final int AD_REPLACE = 0;
    1443 +    public static final int AD_SUM = 1;
    1444 +
    1445 +    int additiveType = AD_REPLACE;
    1446 +   
    1447 +    /** Accumlative state */
    1448 +    public static final int AC_REPLACE = 0;
    1449 +    public static final int AC_SUM = 1;
    1450 +
    1451 +    int accumulateType = AC_REPLACE;
    1452 +
    1453 +    /** Creates a new instance of AnimateEle */
    1454 +    public AnimationElement()
    1455 +    {
    1456 +    }
    1457 +
    1458 +    public static String animationElementToString(int attrValue)
    1459 +    {
    1460 +        switch (attrValue)
    1461 +        {
    1462 +            case AT_CSS:
    1463 +                return "CSS";
    1464 +            case AT_XML:
    1465 +                return "XML";
    1466 +            case AT_AUTO:
    1467 +                return "AUTO";
    1468 +            default:
    1469 +                throw new RuntimeException("Unknown element type");
    1470 +        }
    1471 +    }
    1472 +   
    1473 +    public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
    1474 +    {
    1475 +               //Load style string
    1476 +        super.loaderStartElement(helper, attrs, parent);
    1477 +
    1478 +        attribName = attrs.getValue("attributeName");
    1479 +        String attribType = attrs.getValue("attributeType");
    1480 +        if (attribType != null)
    1481 +        {
    1482 +            attribType = attribType.toLowerCase();
    1483 +            if (attribType.equals("css")) this.attribType = AT_CSS;
    1484 +            else if (attribType.equals("xml")) this.attribType = AT_XML;
    1485 +        }
    1486 +
    1487 +        String beginTime = attrs.getValue("begin");
    1488 +        String durTime = attrs.getValue("dur");
    1489 +        String endTime = attrs.getValue("end");
    1490 +
    1491 +        try
    1492 +        {
    1493 +            if (beginTime != null)
    1494 +            {
    1495 +                helper.animTimeParser.ReInit(new StringReader(beginTime));
    1496 +                this.beginTime = helper.animTimeParser.Expr();
    1497 +                this.beginTime.setParentElement(this);
    1498 +            }
    1499 +
    1500 +            if (durTime != null)
    1501 +            {
    1502 +                helper.animTimeParser.ReInit(new StringReader(durTime));
    1503 +                this.durTime = helper.animTimeParser.Expr();
    1504 +                this.durTime.setParentElement(this);
    1505 +            }
    1506 +
    1507 +            if (endTime != null)
    1508 +            {
    1509 +                helper.animTimeParser.ReInit(new StringReader(endTime));
    1510 +                this.endTime = helper.animTimeParser.Expr();
    1511 +                this.endTime.setParentElement(this);
    1512 +            }
    1513 +        }
    1514 +        catch (Exception e)
    1515 +        {
    1516 +            throw new SAXException(e);
    1517 +        }
    1518 +       
    1519 +//        this.beginTime = TimeBase.parseTime(beginTime);
    1520 +//        this.durTime = TimeBase.parseTime(durTime);
    1521 +//        this.endTime = TimeBase.parseTime(endTime);
    1522 +
    1523 +        String fill = attrs.getValue("fill");
    1524 +
    1525 +        if (fill != null)
    1526 +        {
    1527 +            if (fill.equals("remove")) this.fillType = FT_REMOVE;
    1528 +            if (fill.equals("freeze")) this.fillType = FT_FREEZE;
    1529 +            if (fill.equals("hold")) this.fillType = FT_HOLD;
    1530 +            if (fill.equals("transiton")) this.fillType = FT_TRANSITION;
    1531 +            if (fill.equals("auto")) this.fillType = FT_AUTO;
    1532 +            if (fill.equals("default")) this.fillType = FT_DEFAULT;
    1533 +        }
    1534 +       
    1535 +        String additiveStrn = attrs.getValue("additive");
    1536 +       
    1537 +        if (additiveStrn != null)
    1538 +        {
    1539 +            if (additiveStrn.equals("replace")) this.additiveType = AD_REPLACE;
    1540 +            if (additiveStrn.equals("sum")) this.additiveType = AD_SUM;
    1541 +        }
    1542 +       
    1543 +        String accumulateStrn = attrs.getValue("accumulate");
    1544 +       
    1545 +        if (accumulateStrn != null)
    1546 +        {
    1547 +            if (accumulateStrn.equals("replace")) this.accumulateType = AC_REPLACE;
    1548 +            if (accumulateStrn.equals("sum")) this.accumulateType = AC_SUM;
    1549 +        }
    1550 +    }
    1551 +
    1552 +    public String getAttribName() { return attribName; }
    1553 +    public int getAttribType() { return attribType; }
    1554 +    public int getAdditiveType() { return additiveType; }
    1555 +    public int getAccumulateType() { return accumulateType; }
    1556 +
    1557 +    public void evalParametric(AnimationTimeEval state, double curTime)
    1558 +    {
    1559 +        evalParametric(state, curTime, Double.NaN, Double.NaN);
    1560 +    }
    1561 +
    1562 +    /**
    1563 +     * Compares current time to start and end times and determines what degree
    1564 +     * of time interpolation this track currently represents.  Returns
    1565 +     * Float.NaN if this track cannot be evaluated at the passed time (ie,
    1566 +     * it is before or past the end of the track, or it depends upon
    1567 +     * an unknown event)
    1568 +     * @param state - A structure that will be filled with information
    1569 +     * regarding the applicability of this animatoin element at the passed
    1570 +     * time.
    1571 +     * @param curTime - Current time in seconds
    1572 +     * @param repeatCount - Optional number of repetitions of length 'dur' to
    1573 +     * do.  Set to Double.NaN to not consider this in the calculation.
    1574 +     * @param repeatDur - Optional amoun tof time to repeat the animaiton.
    1575 +     * Set to Double.NaN to not consider this in the calculation.
    1576 +     */
    1577 +    protected void evalParametric(AnimationTimeEval state, double curTime, double repeatCount, double repeatDur)
    1578 +    {
    1579 +        double begin = (beginTime == null) ? 0 : beginTime.evalTime();
    1580 +        if (Double.isNaN(begin) || begin > curTime)
    1581 +        {
    1582 +            state.set(Double.NaN, 0);
    1583 +            return;
    1584 +        }
    1585 +
    1586 +        double dur = (durTime == null) ? Double.NaN : durTime.evalTime();
    1587 +        if (Double.isNaN(dur))
    1588 +        {
    1589 +            state.set(Double.NaN, 0);
    1590 +            return;
    1591 +        }
    1592 +
    1593 +        //Determine end point of this animation
    1594 +        double end = (endTime == null) ? Double.NaN : endTime.evalTime();
    1595 +        double repeat;
    1596 +//        if (Double.isNaN(repeatDur))
    1597 +//        {
    1598 +//            repeatDur = dur;
    1599 +//        }
    1600 +        if (Double.isNaN(repeatCount) && Double.isNaN(repeatDur))
    1601 +        {
    1602 +            repeat = Double.NaN;
    1603 +        }
    1604 +        else
    1605 +        {
    1606 +            repeat = Math.min(
    1607 +                Double.isNaN(repeatCount) ? Double.POSITIVE_INFINITY : dur * repeatCount,
    1608 +                Double.isNaN(repeatDur) ? Double.POSITIVE_INFINITY : repeatDur);
    1609 +        }
    1610 +        if (Double.isNaN(repeat) && Double.isNaN(end))
    1611 +        {
    1612 +            //If neither and end point nor a repeat is specified, end point is
    1613 +            // implied by duration.
    1614 +            end = begin + dur;
    1615 +        }
    1616 +
    1617 +        double finishTime;
    1618 +        if (Double.isNaN(end))
    1619 +        {
    1620 +            finishTime = begin + repeat;
    1621 +        }
    1622 +        else if (Double.isNaN(repeat))
    1623 +        {
    1624 +            finishTime = end;
    1625 +        }
    1626 +        else
    1627 +        {
    1628 +            finishTime = Math.min(end, repeat);
    1629 +        }
    1630 +       
    1631 +        double evalTime = Math.min(curTime, finishTime);
    1632 +//        if (curTime > finishTime) evalTime = finishTime;
    1633 +       
    1634 +       
    1635 +//        double evalTime = curTime;
    1636 +
    1637 +//        boolean pastEnd = curTime > evalTime;
    1638 +       
    1639 +//        if (!Double.isNaN(end) && curTime > end) { pastEnd = true; evalTime = Math.min(evalTime, end); }
    1640 +//        if (!Double.isNaN(repeat) && curTime > repeat) { pastEnd = true; evalTime = Math.min(evalTime, repeat); }
    1641 +       
    1642 +        double ratio = (evalTime - begin) / dur;
    1643 +        int rep = (int)ratio;
    1644 +        double interp = ratio - rep;
    1645 +       
    1646 +        //Adjust for roundoff
    1647 +        if (interp < 0.00001) interp = 0;
    1648 +
    1649 +//        state.set(interp, rep);
    1650 +//        if (!pastEnd)
    1651 +//        {
    1652 +//            state.set(interp, rep, false);
    1653 +//            return;
    1654 +//        }
    1655 +
    1656 +        //If we are still within the clip, return value
    1657 +        if (curTime == evalTime)
    1658 +        {
    1659 +            state.set(interp, rep);
    1660 +            return;
    1661 +        }
    1662 +       
    1663 +        //We are past end of clip.  Determine to clamp or ignore.
    1664 +        switch (fillType)
    1665 +        {
    1666 +            default:
    1667 +            case FT_REMOVE:
    1668 +            case FT_AUTO:
    1669 +            case FT_DEFAULT:
    1670 +                state.set(Double.NaN, rep);
    1671 +                return;
    1672 +            case FT_FREEZE:
    1673 +            case FT_HOLD:
    1674 +            case FT_TRANSITION:
    1675 +                state.set(interp == 0 ? 1 : interp, rep);
    1676 +                return;
    1677 +        }
    1678 +
    1679 +    }
    1680 +
    1681 +    double evalStartTime()
    1682 +    {
    1683 +        return beginTime == null ? Double.NaN : beginTime.evalTime();
    1684 +    }
    1685 +
    1686 +    double evalDurTime()
    1687 +    {
    1688 +        return durTime == null ? Double.NaN : durTime.evalTime();
    1689 +    }
    1690 +
    1691 +    /**
    1692 +     * Evaluates the ending time of this element.  Returns 0 if not specified.
    1693 +     *
    1694 +     * @see hasEndTime
    1695 +     */
    1696 +    double evalEndTime()
    1697 +    {
    1698 +        return endTime == null ? Double.NaN : endTime.evalTime();
    1699 +    }
    1700 +
    1701 +    /**
    1702 +     * Checks to see if an end time has been specified for this element.
    1703 +     */
    1704 +    boolean hasEndTime() { return endTime != null; }
    1705 +
    1706 +    /**
    1707 +     * Updates all attributes in this diagram associated with a time event.
    1708 +     * Ie, all attributes with track information.
    1709 +     * @return - true if this node has changed state as a result of the time
    1710 +     * update
    1711 +     */
    1712 +    public boolean updateTime(double curTime)
    1713 +    {
    1714 +        //Animation elements to not change with time
    1715 +        return false;
    1716 +    }
    1717 +
    1718 +    public void rebuild() throws SVGException
    1719 +    {
    1720 +        AnimTimeParser animTimeParser = new AnimTimeParser(new StringReader(""));
    1721 +
    1722 +        rebuild(animTimeParser);
    1723 +    }
    1724 +
    1725 +    protected void rebuild(AnimTimeParser animTimeParser) throws SVGException
    1726 +    {
    1727 +        StyleAttribute sty = new StyleAttribute();
    1728 +
    1729 +        if (getPres(sty.setName("begin")))
    1730 +        {
    1731 +            String newVal = sty.getStringValue();
    1732 +            animTimeParser.ReInit(new StringReader(newVal));
    1733 +            try {
    1734 +                this.beginTime = animTimeParser.Expr();
    1735 +            } catch (ParseException ex) {
    1736 +                ex.printStackTrace();
    1737 +            }
    1738 +        }
    1739 +
    1740 +        if (getPres(sty.setName("dur")))
    1741 +        {
    1742 +            String newVal = sty.getStringValue();
    1743 +            animTimeParser.ReInit(new StringReader(newVal));
    1744 +            try {
    1745 +                this.durTime = animTimeParser.Expr();
    1746 +            } catch (ParseException ex) {
    1747 +                ex.printStackTrace();
    1748 +            }
    1749 +        }
    1750 +
    1751 +        if (getPres(sty.setName("end")))
    1752 +        {
    1753 +            String newVal = sty.getStringValue();
    1754 +            animTimeParser.ReInit(new StringReader(newVal));
    1755 +            try {
    1756 +                this.endTime = animTimeParser.Expr();
    1757 +            } catch (ParseException ex) {
    1758 +                ex.printStackTrace();
    1759 +            }
    1760 +        }
    1761 +
    1762 +        if (getPres(sty.setName("fill")))
    1763 +        {
    1764 +            String newVal = sty.getStringValue();
    1765 +            if (newVal.equals("remove")) this.fillType = FT_REMOVE;
    1766 +            if (newVal.equals("freeze")) this.fillType = FT_FREEZE;
    1767 +            if (newVal.equals("hold")) this.fillType = FT_HOLD;
    1768 +            if (newVal.equals("transiton")) this.fillType = FT_TRANSITION;
    1769 +            if (newVal.equals("auto")) this.fillType = FT_AUTO;
    1770 +            if (newVal.equals("default")) this.fillType = FT_DEFAULT;
    1771 +        }
    1772 +
    1773 +        if (getPres(sty.setName("additive")))
    1774 +        {
    1775 +            String newVal = sty.getStringValue();
    1776 +            if (newVal.equals("replace")) this.additiveType = AD_REPLACE;
    1777 +            if (newVal.equals("sum")) this.additiveType = AD_SUM;
    1778 +        }
    1779 +
    1780 +        if (getPres(sty.setName("accumulate")))
    1781 +        {
    1782 +            String newVal = sty.getStringValue();
    1783 +            if (newVal.equals("replace")) this.accumulateType = AC_REPLACE;
    1784 +            if (newVal.equals("sum")) this.accumulateType = AC_SUM;
    1785 +        }
    1786 +
    1787 +    }
    1788 +}
    1789 Index: core/src/com/kitfox/svg/animation/AnimationTimeEval.java
    1790 ===================================================================
    1791 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    1792 +++ core/src/com/kitfox/svg/animation/AnimationTimeEval.java    2012-06-17 23:56:57.676545050 +0200
    1793 @@ -0,0 +1,65 @@
    1794 +/*
    1795 + * AnimateTimeEval.java
    1796 + *
    1797 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    1798 + *  Copyright (C) 2004 Mark McKay
    1799 + *
    1800 + *  This library is free software; you can redistribute it and/or
    1801 + *  modify it under the terms of the GNU Lesser General Public
    1802 + *  License as published by the Free Software Foundation; either
    1803 + *  version 2.1 of the License, or (at your option) any later version.
    1804 + *
    1805 + *  This library is distributed in the hope that it will be useful,
    1806 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    1807 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    1808 + *  Lesser General Public License for more details.
    1809 + *
    1810 + *  You should have received a copy of the GNU Lesser General Public
    1811 + *  License along with this library; if not, write to the Free Software
    1812 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    1813 + *
    1814 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    1815 + *  projects can be found at http://www.kitfox.com
    1816 + *
    1817 + *
    1818 + * Created on September 21, 2004, 1:31 PM
    1819 + */
    1820 +
    1821 +package com.kitfox.svg.animation;
    1822 +
    1823 +/**
    1824 + *
    1825 + * @author  kitfox
    1826 + */
    1827 +public class AnimationTimeEval
    1828 +{
    1829 +    /**
    1830 +     * Value on [0..1] representing the interpolation value of queried animation
    1831 +     * element, or Double.NaN if element does not provide a valid evalutaion
    1832 +     */
    1833 +    public double interp;
    1834 +   
    1835 +    /**
    1836 +     * Number of completed repetitions
    1837 +     */
    1838 +    public int rep;
    1839 +   
    1840 +    /**
    1841 +     * True if this evaluation is in a frozen state; ie, past the end of the
    1842 +     * track and held in the "freeze" state.
    1843 +     */
    1844 +//    public boolean pastEnd;
    1845 +   
    1846 +    /** Creates a new instance of AnimateTimeEval */
    1847 +    public AnimationTimeEval()
    1848 +    {
    1849 +    }
    1850 +   
    1851 +//    public void set(double interp, int rep, boolean pastEnd)
    1852 +    public void set(double interp, int rep)
    1853 +    {
    1854 +        this.interp = interp;
    1855 +        this.rep = rep;
    1856 +//        this.pastEnd = pastEnd;
    1857 +    }
    1858 +}
    1859 Index: core/src/com/kitfox/svg/animation/Bezier.java
    1860 ===================================================================
    1861 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    1862 +++ core/src/com/kitfox/svg/animation/Bezier.java       2012-06-17 23:56:57.680545050 +0200
    1863 @@ -0,0 +1,201 @@
    1864 +/*
    1865 + * Bezier.java
    1866 + *
    1867 +
    1868 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    1869 + *  Copyright (C) 2004 Mark McKay
    1870 + *
    1871 + *  This library is free software; you can redistribute it and/or
    1872 + *  modify it under the terms of the GNU Lesser General Public
    1873 + *  License as published by the Free Software Foundation; either
    1874 + *  version 2.1 of the License, or (at your option) any later version.
    1875 + *
    1876 + *  This library is distributed in the hope that it will be useful,
    1877 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    1878 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    1879 + *  Lesser General Public License for more details.
    1880 + *
    1881 + *  You should have received a copy of the GNU Lesser General Public
    1882 + *  License along with this library; if not, write to the Free Software
    1883 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    1884 + *
    1885 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    1886 + *  projects can be found at http://www.kitfox.com
    1887 + *
    1888 + * Created on January 14, 2005, 4:08 AM
    1889 + */
    1890 +
    1891 +package com.kitfox.svg.animation;
    1892 +
    1893 +import java.awt.geom.*;
    1894 +
    1895 +/**
    1896 + * http://mathworld.wolfram.com/BezierCurve.html
    1897 + * @author kitfox
    1898 + */
    1899 +public class Bezier
    1900 +{
    1901 +    double length;
    1902 +    double[] coord;
    1903 +
    1904 +    public Bezier(double sx, double sy, double[] coords, int numCoords)
    1905 +    {
    1906 +        setCoords(sx, sy, coords, numCoords);
    1907 +    }
    1908 +   
    1909 +    public void setCoords(double sx, double sy, double[] coords, int numCoords)
    1910 +    {
    1911 +        coord = new double[numCoords * 2 + 2];
    1912 +        coord[0] = sx;
    1913 +        coord[1] = sy;
    1914 +        for (int i = 0; i < numCoords; i++)
    1915 +        {
    1916 +            coord[i * 2 + 2] = coords[i * 2];
    1917 +            coord[i * 2 + 3] = coords[i * 2 + 1];
    1918 +        }
    1919 +       
    1920 +        calcLength();       
    1921 +    }
    1922 +   
    1923 +    /**
    1924 +     * Retuns aproximation of the length of the bezier
    1925 +     */
    1926 +    public double getLength()
    1927 +    {
    1928 +        return length;
    1929 +    }
    1930 +   
    1931 +    private void calcLength()
    1932 +    {
    1933 +        length = 0;
    1934 +        for (int i = 2; i < coord.length; i += 2)
    1935 +        {
    1936 +            length += lineLength(coord[i - 2], coord[i - 1], coord[i], coord[i + 1]);
    1937 +        }
    1938 +    }
    1939 +   
    1940 +    private double lineLength(double x1, double y1, double x2, double y2)
    1941 +    {
    1942 +        double dx = x2 - x1, dy = y2 - y1;
    1943 +        return Math.sqrt(dx * dx + dy * dy);
    1944 +    }
    1945 +   
    1946 +    public Point2D.Double getFinalPoint(Point2D.Double point)
    1947 +    {
    1948 +        point.x = coord[coord.length - 2];
    1949 +        point.y = coord[coord.length - 1];
    1950 +        return point;
    1951 +    }
    1952 +   
    1953 +    public Point2D.Double eval(double param, Point2D.Double point)
    1954 +    {
    1955 +        point.x = 0;
    1956 +        point.y = 0;
    1957 +        int numKnots = coord.length / 2;
    1958 +       
    1959 +        for (int i = 0; i < numKnots; i++)
    1960 +        {
    1961 +            double scale = bernstein(numKnots - 1, i, param);
    1962 +            point.x += coord[i * 2] * scale;
    1963 +            point.y += coord[i * 2 + 1] * scale;
    1964 +        }
    1965 +       
    1966 +        return point;
    1967 +    }
    1968 +   
    1969 +    /**
    1970 +     * Calculates the bernstein polynomial for evaluating parametric bezier
    1971 +     * @param numKnots - one less than number of knots in this curve hull
    1972 +     * @param knotNo - knot we are evaluating Bernstein for
    1973 +     * @param param - Parametric value we are evaluating at
    1974 +     */
    1975 +    private double bernstein(int numKnots, int knotNo, double param)
    1976 +    {
    1977 +        double iParam = 1 - param;
    1978 +        //Faster evaluation for easy cases:
    1979 +        switch (numKnots)
    1980 +        {
    1981 +            case 0:
    1982 +                return 1;
    1983 +            case 1:
    1984 +            {
    1985 +                switch (knotNo)
    1986 +                {
    1987 +                    case 0:
    1988 +                        return iParam;
    1989 +                    case 1:
    1990 +                        return param;
    1991 +                }
    1992 +                break;
    1993 +            }
    1994 +            case 2:
    1995 +            {
    1996 +                switch (knotNo)
    1997 +                {
    1998 +                    case 0:
    1999 +                        return iParam * iParam;
    2000 +                    case 1:
    2001 +                        return 2 * iParam * param;
    2002 +                    case 2:
    2003 +                        return param * param;
    2004 +                }
    2005 +                break;
    2006 +            }
    2007 +            case 3:
    2008 +            {
    2009 +                switch (knotNo)
    2010 +                {
    2011 +                    case 0:
    2012 +                        return iParam * iParam * iParam;
    2013 +                    case 1:
    2014 +                        return 3 * iParam * iParam * param;
    2015 +                    case 2:
    2016 +                        return 3 * iParam * param * param;
    2017 +                    case 3:
    2018 +                        return param * param * param;
    2019 +                }
    2020 +                break;
    2021 +            }
    2022 +        }
    2023 +       
    2024 +        //If this bezier has more than four points, calculate bernstein the hard way
    2025 +        double retVal = 1;
    2026 +        for (int i = 0; i < knotNo; i++)
    2027 +        {
    2028 +            retVal *= param;
    2029 +        }
    2030 +        for (int i = 0; i < numKnots - knotNo; i++)
    2031 +        {
    2032 +            retVal *= iParam;
    2033 +        }
    2034 +        retVal *= choose(numKnots, knotNo);
    2035 +       
    2036 +        return retVal;
    2037 +    }
    2038 +   
    2039 +   
    2040 +   
    2041 +    private int choose(int num, int denom)
    2042 +    {
    2043 +        int denom2 = num - denom;
    2044 +        if (denom < denom2)
    2045 +        {
    2046 +            int tmp = denom;
    2047 +            denom = denom2;
    2048 +            denom2 = tmp;
    2049 +        }
    2050 +       
    2051 +        int prod = 1;
    2052 +        for (int i = num; i > denom; i--)
    2053 +        {
    2054 +            prod *= num;
    2055 +        }
    2056 +       
    2057 +        for (int i = 2; i <= denom2; i++)
    2058 +        {
    2059 +            prod /= i;
    2060 +        }
    2061 +       
    2062 +        return prod;
    2063 +    }
    2064 +}
    2065 Index: core/src/com/kitfox/svg/animation/SetSmil.java
    2066 ===================================================================
    2067 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    2068 +++ core/src/com/kitfox/svg/animation/SetSmil.java      2012-06-17 23:56:57.680545050 +0200
    2069 @@ -0,0 +1,73 @@
    2070 +/*
    2071 + * Set.java
    2072 + *
    2073 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    2074 + *  Copyright (C) 2004 Mark McKay
    2075 + *
    2076 + *  This library is free software; you can redistribute it and/or
    2077 + *  modify it under the terms of the GNU Lesser General Public
    2078 + *  License as published by the Free Software Foundation; either
    2079 + *  version 2.1 of the License, or (at your option) any later version.
    2080 + *
    2081 + *  This library is distributed in the hope that it will be useful,
    2082 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2083 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    2084 + *  Lesser General Public License for more details.
    2085 + *
    2086 + *  You should have received a copy of the GNU Lesser General Public
    2087 + *  License along with this library; if not, write to the Free Software
    2088 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    2089 + *
    2090 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    2091 + *  projects can be found at http://www.kitfox.com
    2092 + *
    2093 + * Created on August 15, 2004, 2:51 AM
    2094 + */
    2095 +
    2096 +package com.kitfox.svg.animation;
    2097 +
    2098 +import com.kitfox.svg.SVGElement;
    2099 +import com.kitfox.svg.SVGException;
    2100 +import com.kitfox.svg.SVGLoaderHelper;
    2101 +import com.kitfox.svg.animation.parser.AnimTimeParser;
    2102 +import com.kitfox.svg.xml.StyleAttribute;
    2103 +import org.xml.sax.Attributes;
    2104 +import org.xml.sax.SAXException;
    2105 +
    2106 +
    2107 +/**
    2108 + * Set is used to set a textual value; most likely for a style element.
    2109 + *
    2110 + * @author Mark McKay
    2111 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    2112 + */
    2113 +public class SetSmil extends AnimationElement
    2114 +{
    2115 +    String toValue;
    2116 +   
    2117 +    /** Creates a new instance of Set */
    2118 +    public SetSmil()
    2119 +    {
    2120 +    }
    2121 +   
    2122 +    public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
    2123 +    {
    2124 +               //Load style string
    2125 +        super.loaderStartElement(helper, attrs, parent);
    2126 +
    2127 +        toValue = attrs.getValue("to");
    2128 +    }
    2129 +
    2130 +    protected void rebuild(AnimTimeParser animTimeParser) throws SVGException
    2131 +    {
    2132 +        super.rebuild(animTimeParser);
    2133 +
    2134 +        StyleAttribute sty = new StyleAttribute();
    2135 +
    2136 +        if (getPres(sty.setName("to")))
    2137 +        {
    2138 +            String newVal = sty.getStringValue();
    2139 +            toValue = newVal;
    2140 +        }
    2141 +    }
    2142 +}
    2143 Index: core/src/com/kitfox/svg/animation/TimeBase.java
    2144 ===================================================================
    2145 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    2146 +++ core/src/com/kitfox/svg/animation/TimeBase.java     2012-06-17 23:56:57.680545050 +0200
    2147 @@ -0,0 +1,99 @@
    2148 +/*
    2149 + * TimeBase.java
    2150 + *
    2151 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    2152 + *  Copyright (C) 2004 Mark McKay
    2153 + *
    2154 + *  This library is free software; you can redistribute it and/or
    2155 + *  modify it under the terms of the GNU Lesser General Public
    2156 + *  License as published by the Free Software Foundation; either
    2157 + *  version 2.1 of the License, or (at your option) any later version.
    2158 + *
    2159 + *  This library is distributed in the hope that it will be useful,
    2160 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2161 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    2162 + *  Lesser General Public License for more details.
    2163 + *
    2164 + *  You should have received a copy of the GNU Lesser General Public
    2165 + *  License along with this library; if not, write to the Free Software
    2166 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    2167 + *
    2168 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    2169 + *  projects can be found at http://www.kitfox.com
    2170 + *
    2171 + * Created on August 15, 2004, 3:31 AM
    2172 + */
    2173 +
    2174 +package com.kitfox.svg.animation;
    2175 +
    2176 +import java.util.regex.*;
    2177 +
    2178 +/**
    2179 + * SVG has a complicated way of specifying time.  Potentially, a time could
    2180 + * be represened as a summation of discrete times and times of other animation
    2181 + * events.  This provides a root for the many elements we will need to define
    2182 + * time.
    2183 + *
    2184 + * @author Mark McKay
    2185 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    2186 + */
    2187 +abstract public class TimeBase
    2188 +{
    2189 +    static final Matcher matchIndefinite = Pattern.compile("\\s*indefinite\\s*").matcher("");
    2190 +    static final Matcher matchUnitTime = Pattern.compile("\\s*([-+]?((\\d*\\.\\d+)|(\\d+))([-+]?[eE]\\d+)?)\\s*(h|min|s|ms)?\\s*").matcher("");
    2191 +   
    2192 +    /*
    2193 +    public static TimeBase parseTime(String text)
    2194 +    {
    2195 +        if (text == null) return null;
    2196 +       
    2197 +        if (text.indexOf('+') == -1)
    2198 +        {
    2199 +            return parseTimeComponent(text);
    2200 +        }
    2201 +       
    2202 +        return new TimeCompound(text);
    2203 +    }
    2204 +     */
    2205 +   
    2206 +    protected static TimeBase parseTimeComponent(String text)
    2207 +    {
    2208 +        matchIndefinite.reset(text);
    2209 +        if (matchIndefinite.matches()) return new TimeIndefinite();
    2210 +       
    2211 +        matchUnitTime.reset(text);
    2212 +        if (matchUnitTime.matches())
    2213 +        {
    2214 +            String val = matchUnitTime.group(1);
    2215 +            String units = matchUnitTime.group(6);
    2216 +           
    2217 +            double time = 0;
    2218 +            try { time = Double.parseDouble(val); }
    2219 +            catch (Exception e) {}
    2220 +           
    2221 +            if (units.equals("ms")) time *= .001;
    2222 +            else if (units.equals("min")) time *= 60;
    2223 +            else if (units.equals("h")) time *= 3600;
    2224 +           
    2225 +            return new TimeDiscrete(time);
    2226 +        }
    2227 +       
    2228 +        return null;
    2229 +    }
    2230 +   
    2231 +    /**
    2232 +     * Calculates the (greater than or equal to 0) time in seconds this
    2233 +     * time represents.  If the time cannot be determined, returns
    2234 +     * Double.NaN.  If this represents an infinte amount of time, returns
    2235 +     * Double.POSITIVE_INFINITY.
    2236 +     */
    2237 +    abstract public double evalTime();
    2238 +   
    2239 +    /**
    2240 +     * Some time elements need to refer to the animation element that contains
    2241 +     * them to evaluate correctly
    2242 +     */
    2243 +    public void setParentElement(AnimationElement ele)
    2244 +    {
    2245 +    }
    2246 +}
    2247 Index: core/src/com/kitfox/svg/animation/TimeCompound.java
    2248 ===================================================================
    2249 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    2250 +++ core/src/com/kitfox/svg/animation/TimeCompound.java 2012-06-17 23:56:57.680545050 +0200
    2251 @@ -0,0 +1,84 @@
    2252 +/*
    2253 + * TimeDiscrete.java
    2254 + *
    2255 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    2256 + *  Copyright (C) 2004 Mark McKay
    2257 + *
    2258 + *  This library is free software; you can redistribute it and/or
    2259 + *  modify it under the terms of the GNU Lesser General Public
    2260 + *  License as published by the Free Software Foundation; either
    2261 + *  version 2.1 of the License, or (at your option) any later version.
    2262 + *
    2263 + *  This library is distributed in the hope that it will be useful,
    2264 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2265 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    2266 + *  Lesser General Public License for more details.
    2267 + *
    2268 + *  You should have received a copy of the GNU Lesser General Public
    2269 + *  License along with this library; if not, write to the Free Software
    2270 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    2271 + *
    2272 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    2273 + *  projects can be found at http://www.kitfox.com
    2274 + *
    2275 + * Created on August 15, 2004, 3:33 AM
    2276 + */
    2277 +
    2278 +package com.kitfox.svg.animation;
    2279 +
    2280 +import java.util.Collections;
    2281 +import java.util.Iterator;
    2282 +import java.util.List;
    2283 +import java.util.regex.Pattern;
    2284 +
    2285 +
    2286 +/**
    2287 + * This represents a summation of other time elements.  It is used for complex
    2288 + * timing events with offsets.
    2289 + *
    2290 + * @author Mark McKay
    2291 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    2292 + */
    2293 +public class TimeCompound extends TimeBase
    2294 +{
    2295 +    static final Pattern patPlus = Pattern.compile("\\+");
    2296 +   
    2297 +    /**
    2298 +     * This is a list of times.  This element's time is calculated as the greatest
    2299 +     * member that is less than the current time.
    2300 +    */
    2301 +    final List componentTimes;
    2302 +
    2303 +    private AnimationElement parent;
    2304 +   
    2305 +    /** Creates a new instance of TimeDiscrete */
    2306 +    public TimeCompound(List timeBases)
    2307 +    {
    2308 +        componentTimes = Collections.unmodifiableList(timeBases);
    2309 +    }
    2310 +   
    2311 +    public double evalTime()
    2312 +    {
    2313 +        double agg = 0.0;
    2314 +       
    2315 +        for (Iterator it = componentTimes.iterator(); it.hasNext();)
    2316 +        {
    2317 +            TimeBase timeEle = (TimeBase)it.next();
    2318 +            double time = timeEle.evalTime();
    2319 +            agg += time;
    2320 +        }
    2321 +       
    2322 +        return agg;
    2323 +    }
    2324 +   
    2325 +    public void setParentElement(AnimationElement ele)
    2326 +    {
    2327 +        this.parent = ele;
    2328 +       
    2329 +        for (Iterator it = componentTimes.iterator(); it.hasNext();)
    2330 +        {
    2331 +            TimeBase timeEle = (TimeBase)it.next();
    2332 +            timeEle.setParentElement(ele);
    2333 +        }
    2334 +    }
    2335 +}
    2336 Index: core/src/com/kitfox/svg/animation/TimeDiscrete.java
    2337 ===================================================================
    2338 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    2339 +++ core/src/com/kitfox/svg/animation/TimeDiscrete.java 2012-06-17 23:56:57.680545050 +0200
    2340 @@ -0,0 +1,51 @@
    2341 +/*
    2342 + * TimeDiscrete.java
    2343 + *
    2344 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    2345 + *  Copyright (C) 2004 Mark McKay
    2346 + *
    2347 + *  This library is free software; you can redistribute it and/or
    2348 + *  modify it under the terms of the GNU Lesser General Public
    2349 + *  License as published by the Free Software Foundation; either
    2350 + *  version 2.1 of the License, or (at your option) any later version.
    2351 + *
    2352 + *  This library is distributed in the hope that it will be useful,
    2353 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2354 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    2355 + *  Lesser General Public License for more details.
    2356 + *
    2357 + *  You should have received a copy of the GNU Lesser General Public
    2358 + *  License along with this library; if not, write to the Free Software
    2359 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    2360 + *
    2361 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    2362 + *  projects can be found at http://www.kitfox.com
    2363 + *
    2364 + * Created on August 15, 2004, 3:33 AM
    2365 + */
    2366 +
    2367 +package com.kitfox.svg.animation;
    2368 +
    2369 +/**
    2370 + * This is a time that represents a specific number of milliseconds
    2371 + *
    2372 + * @author Mark McKay
    2373 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    2374 + */
    2375 +public class TimeDiscrete extends TimeBase
    2376 +{
    2377 +    //Milliseconds of delay
    2378 +    double secs;
    2379 +   
    2380 +    /** Creates a new instance of TimeDiscrete */
    2381 +    public TimeDiscrete(double secs)
    2382 +    {
    2383 +        this.secs = secs;
    2384 +    }
    2385 +   
    2386 +    public double evalTime()
    2387 +    {
    2388 +        return secs;
    2389 +    }
    2390 +   
    2391 +}
    2392 Index: core/src/com/kitfox/svg/animation/TimeIndefinite.java
    2393 ===================================================================
    2394 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    2395 +++ core/src/com/kitfox/svg/animation/TimeIndefinite.java       2012-06-17 23:56:57.680545050 +0200
    2396 @@ -0,0 +1,48 @@
    2397 +/*
    2398 + * TimeDiscrete.java
    2399 + *
    2400 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    2401 + *  Copyright (C) 2004 Mark McKay
    2402 + *
    2403 + *  This library is free software; you can redistribute it and/or
    2404 + *  modify it under the terms of the GNU Lesser General Public
    2405 + *  License as published by the Free Software Foundation; either
    2406 + *  version 2.1 of the License, or (at your option) any later version.
    2407 + *
    2408 + *  This library is distributed in the hope that it will be useful,
    2409 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2410 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    2411 + *  Lesser General Public License for more details.
    2412 + *
    2413 + *  You should have received a copy of the GNU Lesser General Public
    2414 + *  License along with this library; if not, write to the Free Software
    2415 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    2416 + *
    2417 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    2418 + *  projects can be found at http://www.kitfox.com
    2419 + *
    2420 + * Created on August 15, 2004, 3:33 AM
    2421 + */
    2422 +
    2423 +package com.kitfox.svg.animation;
    2424 +
    2425 +/**
    2426 + * This represents the indefinite (infinite) amount of time.
    2427 + *
    2428 + * @author Mark McKay
    2429 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    2430 + */
    2431 +public class TimeIndefinite extends TimeBase
    2432 +{
    2433 +   
    2434 +    /** Creates a new instance of TimeDiscrete */
    2435 +    public TimeIndefinite()
    2436 +    {
    2437 +    }
    2438 +   
    2439 +    public double evalTime()
    2440 +    {
    2441 +        return Double.POSITIVE_INFINITY;
    2442 +    }
    2443 +   
    2444 +}
    2445 Index: core/src/com/kitfox/svg/animation/TimeLookup.java
    2446 ===================================================================
    2447 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    2448 +++ core/src/com/kitfox/svg/animation/TimeLookup.java   2012-06-17 23:56:57.684545050 +0200
    2449 @@ -0,0 +1,75 @@
    2450 +/*
    2451 + * TimeDiscrete.java
    2452 + *
    2453 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    2454 + *  Copyright (C) 2004 Mark McKay
    2455 + *
    2456 + *  This library is free software; you can redistribute it and/or
    2457 + *  modify it under the terms of the GNU Lesser General Public
    2458 + *  License as published by the Free Software Foundation; either
    2459 + *  version 2.1 of the License, or (at your option) any later version.
    2460 + *
    2461 + *  This library is distributed in the hope that it will be useful,
    2462 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2463 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    2464 + *  Lesser General Public License for more details.
    2465 + *
    2466 + *  You should have received a copy of the GNU Lesser General Public
    2467 + *  License along with this library; if not, write to the Free Software
    2468 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    2469 + *
    2470 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    2471 + *  projects can be found at http://www.kitfox.com
    2472 + *
    2473 + * Created on August 15, 2004, 3:33 AM
    2474 + */
    2475 +
    2476 +package com.kitfox.svg.animation;
    2477 +
    2478 +/**
    2479 + * This is a time that represents a specific number of milliseconds
    2480 + *
    2481 + * @author Mark McKay
    2482 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    2483 + */
    2484 +public class TimeLookup extends TimeBase
    2485 +{
    2486 +    /**
    2487 +     * This time can only be resolved in relation to it's parent
    2488 +     */
    2489 +    private AnimationElement parent;
    2490 +   
    2491 +    /**
    2492 +     * Node this lookup acts upon
    2493 +     */
    2494 +    String node;
    2495 +   
    2496 +    /**
    2497 +     * Event to evalutae on this node
    2498 +     */
    2499 +    String event;
    2500 +   
    2501 +    /**
    2502 +     * Optional parameter used by some events
    2503 +     */
    2504 +    String paramList;
    2505 +   
    2506 +    /** Creates a new instance of TimeDiscrete */
    2507 +    public TimeLookup(AnimationElement parent, String node, String event, String paramList)
    2508 +    {
    2509 +        this.parent = parent;
    2510 +        this.node = node;
    2511 +        this.event = event;
    2512 +        this.paramList = paramList;
    2513 +    }
    2514 +   
    2515 +    public double evalTime()
    2516 +    {
    2517 +        return 0.0;
    2518 +    }
    2519 +   
    2520 +    public void setParentElement(AnimationElement ele)
    2521 +    {
    2522 +        parent = ele;
    2523 +    }
    2524 +}
    2525 Index: core/src/com/kitfox/svg/animation/TimeSum.java
    2526 ===================================================================
    2527 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    2528 +++ core/src/com/kitfox/svg/animation/TimeSum.java      2012-06-17 23:56:57.684545050 +0200
    2529 @@ -0,0 +1,60 @@
    2530 +/*
    2531 + * TimeDiscrete.java
    2532 + *
    2533 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    2534 + *  Copyright (C) 2004 Mark McKay
    2535 + *
    2536 + *  This library is free software; you can redistribute it and/or
    2537 + *  modify it under the terms of the GNU Lesser General Public
    2538 + *  License as published by the Free Software Foundation; either
    2539 + *  version 2.1 of the License, or (at your option) any later version.
    2540 + *
    2541 + *  This library is distributed in the hope that it will be useful,
    2542 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2543 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    2544 + *  Lesser General Public License for more details.
    2545 + *
    2546 + *  You should have received a copy of the GNU Lesser General Public
    2547 + *  License along with this library; if not, write to the Free Software
    2548 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    2549 + *
    2550 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    2551 + *  projects can be found at http://www.kitfox.com
    2552 + *
    2553 + * Created on August 15, 2004, 3:33 AM
    2554 + */
    2555 +
    2556 +package com.kitfox.svg.animation;
    2557 +
    2558 +/**
    2559 + * This is a time that represents a specific number of milliseconds
    2560 + *
    2561 + * @author Mark McKay
    2562 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    2563 + */
    2564 +public class TimeSum extends TimeBase
    2565 +{
    2566 +    //Milliseconds of delay
    2567 +    TimeBase t1;
    2568 +    TimeBase t2;
    2569 +    boolean add;
    2570 +   
    2571 +    /** Creates a new instance of TimeDiscrete */
    2572 +    public TimeSum(TimeBase t1, TimeBase t2, boolean add)
    2573 +    {
    2574 +        this.t1 = t1;
    2575 +        this.t2 = t2;
    2576 +        this.add = add;
    2577 +    }
    2578 +   
    2579 +    public double evalTime()
    2580 +    {
    2581 +        return add ? t1.evalTime() + t2.evalTime() : t1.evalTime() - t2.evalTime();
    2582 +    }
    2583 +   
    2584 +    public void setParentElement(AnimationElement ele)
    2585 +    {
    2586 +        t1.setParentElement(ele);
    2587 +        t2.setParentElement(ele);
    2588 +    }
    2589 +}
    2590 Index: core/src/com/kitfox/svg/animation/TrackBase.java
    2591 ===================================================================
    2592 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    2593 +++ core/src/com/kitfox/svg/animation/TrackBase.java    2012-06-17 23:56:57.684545050 +0200
    2594 @@ -0,0 +1,103 @@
    2595 +/*
    2596 + * TrackManager.java
    2597 + *
    2598 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    2599 + *  Copyright (C) 2004 Mark McKay
    2600 + *
    2601 + *  This library is free software; you can redistribute it and/or
    2602 + *  modify it under the terms of the GNU Lesser General Public
    2603 + *  License as published by the Free Software Foundation; either
    2604 + *  version 2.1 of the License, or (at your option) any later version.
    2605 + *
    2606 + *  This library is distributed in the hope that it will be useful,
    2607 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2608 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    2609 + *  Lesser General Public License for more details.
    2610 + *
    2611 + *  You should have received a copy of the GNU Lesser General Public
    2612 + *  License along with this library; if not, write to the Free Software
    2613 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    2614 + *
    2615 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    2616 + *  projects can be found at http://www.kitfox.com
    2617 + *
    2618 + * Created on August 15, 2004, 11:34 PM
    2619 + */
    2620 +
    2621 +package com.kitfox.svg.animation;
    2622 +
    2623 +import java.util.*;
    2624 +
    2625 +import com.kitfox.svg.xml.*;
    2626 +import com.kitfox.svg.*;
    2627 +
    2628 +/**
    2629 + * A track holds the animation events for a single parameter of a single SVG
    2630 + * element.  It also contains the default value for the element, should the
    2631 + * user want to see the 'unanimated' value.
    2632 + *
    2633 + * @author Mark McKay
    2634 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    2635 + */
    2636 +abstract public class TrackBase
    2637 +{
    2638 +    protected final String attribName;
    2639 +    protected final int attribType;  //AnimationElement.AT_*
    2640 +
    2641 +    /** Element we're animating */
    2642 +    protected final SVGElement parent;
    2643 +   
    2644 +    //It doesn't make sense to sort this, since some events will depend on
    2645 +    // other events - in many cases, there will be no meaningful sorted order.
    2646 +    final ArrayList animEvents = new ArrayList();
    2647 +   
    2648 +    /** Creates a new instance of TrackManager */
    2649 +//    public TrackBase(SVGElement parent)
    2650 +//    {
    2651 +//        this(parent, "", AnimationElement.AT_AUTO);
    2652 +//    }
    2653 +   
    2654 +    /**
    2655 +     * Creates a track that would be valid for the name and type of element
    2656 +     * passed in.  Does not actually add this elemnt to the track.
    2657 +     */
    2658 +    public TrackBase(SVGElement parent, AnimationElement ele) throws SVGElementException
    2659 +    {
    2660 +        this(parent, ele.getAttribName(), ele.getAttribType());
    2661 +    }
    2662 +   
    2663 +    public TrackBase(SVGElement parent, String attribName, int attribType) throws SVGElementException
    2664 +    {
    2665 +        this.parent = parent;
    2666 +        this.attribName = attribName;
    2667 +        this.attribType = attribType;
    2668 +       
    2669 +        //Make sure parent has an attribute we will write to
    2670 +        if (attribType == AnimationElement.AT_AUTO
    2671 +            && !parent.hasAttribute(attribName, AnimationElement.AT_CSS)
    2672 +            && !parent.hasAttribute(attribName, AnimationElement.AT_XML))
    2673 +        {
    2674 +            parent.addAttribute(attribName, AnimationElement.AT_CSS, "");
    2675 +        }
    2676 +        else if (!parent.hasAttribute(attribName, attribType))
    2677 +        {
    2678 +            parent.addAttribute(attribName, attribType, "");
    2679 +        }
    2680 +    }
    2681 +   
    2682 +    public String getAttribName() { return attribName; }
    2683 +    public int getAttribType() { return attribType; }
    2684 +   
    2685 +    public void addElement(AnimationElement ele)
    2686 +    {
    2687 +        animEvents.add(ele);
    2688 +    }
    2689 +   
    2690 +    /**
    2691 +     * Returns a StyleAttribute representing the value of this track at the
    2692 +     * passed time.  If this track does not apply, returns null.
    2693 +     * @return - True if successful, false if a value could not be obtained
    2694 +     */
    2695 +    abstract public boolean getValue(StyleAttribute attrib, double curTime) throws SVGException;
    2696 +   
    2697 +}
    2698 Index: core/src/com/kitfox/svg/animation/TrackColor.java
    2699 ===================================================================
    2700 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    2701 +++ core/src/com/kitfox/svg/animation/TrackColor.java   2012-06-17 23:56:57.684545050 +0200
    2702 @@ -0,0 +1,95 @@
    2703 +/*
    2704 + * TrackManager.java
    2705 + *
    2706 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    2707 + *  Copyright (C) 2004 Mark McKay
    2708 + *
    2709 + *  This library is free software; you can redistribute it and/or
    2710 + *  modify it under the terms of the GNU Lesser General Public
    2711 + *  License as published by the Free Software Foundation; either
    2712 + *  version 2.1 of the License, or (at your option) any later version.
    2713 + *
    2714 + *  This library is distributed in the hope that it will be useful,
    2715 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2716 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    2717 + *  Lesser General Public License for more details.
    2718 + *
    2719 + *  You should have received a copy of the GNU Lesser General Public
    2720 + *  License along with this library; if not, write to the Free Software
    2721 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    2722 + *
    2723 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    2724 + *  projects can be found at http://www.kitfox.com
    2725 + *
    2726 + * Created on September 21, 2004, 11:34 PM
    2727 + */
    2728 +
    2729 +package com.kitfox.svg.animation;
    2730 +
    2731 +import com.kitfox.svg.xml.StyleAttribute;
    2732 +import java.awt.*;
    2733 +import java.util.*;
    2734 +
    2735 +import com.kitfox.svg.*;
    2736 +import com.kitfox.svg.xml.*;
    2737 +
    2738 +/**
    2739 + * A track holds the animation events for a single parameter of a single SVG
    2740 + * element.  It also contains the default value for the element, should the
    2741 + * user want to see the 'unanimated' value.
    2742 + *
    2743 + * @author Mark McKay
    2744 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    2745 + */
    2746 +public class TrackColor extends TrackBase
    2747 +{
    2748 +
    2749 +    public TrackColor(AnimationElement ele) throws SVGElementException
    2750 +    {
    2751 +        super(ele.getParent(), ele);
    2752 +    }
    2753 +
    2754 +    public boolean getValue(StyleAttribute attrib, double curTime)
    2755 +    {
    2756 +        Color col = getValue(curTime);
    2757 +        if (col == null) return false;
    2758 +
    2759 +        attrib.setStringValue("#" + Integer.toHexString(col.getRGB()));
    2760 +        return true;
    2761 +    }
    2762 +
    2763 +    public Color getValue(double curTime)
    2764 +    {
    2765 +        Color retVal = null;
    2766 +        AnimationTimeEval state = new AnimationTimeEval();
    2767 +
    2768 +        for (Iterator it = animEvents.iterator(); it.hasNext();)
    2769 +        {
    2770 +            AnimateBase ele = (AnimateBase)it.next();
    2771 +            AnimateColorIface eleColor = (AnimateColorIface)ele;
    2772 +            ele.evalParametric(state, curTime);
    2773 +
    2774 +            //Reject value if it is in the invalid state
    2775 +            if (Double.isNaN(state.interp)) continue;
    2776 +
    2777 +            if (retVal == null)
    2778 +            {
    2779 +                retVal = eleColor.evalColor(state.interp);
    2780 +                continue;
    2781 +            }
    2782 +           
    2783 +            Color curCol = eleColor.evalColor(state.interp);
    2784 +            switch (ele.getAdditiveType())
    2785 +            {
    2786 +                case AnimationElement.AD_REPLACE:
    2787 +                    retVal = curCol;
    2788 +                    break;
    2789 +                case AnimationElement.AD_SUM:
    2790 +                    retVal = new Color(curCol.getRed() + retVal.getRed(), curCol.getGreen() + retVal.getGreen(), curCol.getBlue() + retVal.getBlue());
    2791 +                    break;
    2792 +            }
    2793 +        }
    2794 +
    2795 +        return retVal;
    2796 +    }
    2797 +}
    2798 Index: core/src/com/kitfox/svg/animation/TrackDouble.java
    2799 ===================================================================
    2800 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    2801 +++ core/src/com/kitfox/svg/animation/TrackDouble.java  2012-06-17 23:56:57.684545050 +0200
    2802 @@ -0,0 +1,119 @@
    2803 +/*
    2804 + * TrackManager.java
    2805 + *
    2806 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    2807 + *  Copyright (C) 2004 Mark McKay
    2808 + *
    2809 + *  This library is free software; you can redistribute it and/or
    2810 + *  modify it under the terms of the GNU Lesser General Public
    2811 + *  License as published by the Free Software Foundation; either
    2812 + *  version 2.1 of the License, or (at your option) any later version.
    2813 + *
    2814 + *  This library is distributed in the hope that it will be useful,
    2815 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2816 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    2817 + *  Lesser General Public License for more details.
    2818 + *
    2819 + *  You should have received a copy of the GNU Lesser General Public
    2820 + *  License along with this library; if not, write to the Free Software
    2821 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    2822 + *
    2823 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    2824 + *  projects can be found at http://www.kitfox.com
    2825 + *
    2826 + * Created on August 15, 2004, 11:34 PM
    2827 + */
    2828 +
    2829 +package com.kitfox.svg.animation;
    2830 +
    2831 +import com.kitfox.svg.xml.StyleAttribute;
    2832 +import java.util.*;
    2833 +
    2834 +import com.kitfox.svg.*;
    2835 +import com.kitfox.svg.xml.*;
    2836 +
    2837 +/**
    2838 + * A track holds the animation events for a single parameter of a single SVG
    2839 + * element.  It also contains the default value for the element, should the
    2840 + * user want to see the 'unanimated' value.
    2841 + *
    2842 + * @author Mark McKay
    2843 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    2844 + */
    2845 +public class TrackDouble extends TrackBase
    2846 +{
    2847 +    public TrackDouble(AnimationElement ele) throws SVGElementException
    2848 +    {
    2849 +        super(ele.getParent(), ele);
    2850 +    }
    2851 +
    2852 +    public boolean getValue(StyleAttribute attrib, double curTime)
    2853 +    {
    2854 +        double val = getValue(curTime);
    2855 +        if (Double.isNaN(val)) return false;
    2856 +
    2857 +        attrib.setStringValue("" + val);
    2858 +        return true;
    2859 +    }
    2860 +
    2861 +    public double getValue(double curTime)
    2862 +    {
    2863 +        double retVal = Double.NaN;
    2864 +       
    2865 +        StyleAttribute attr = null;
    2866 +        switch (attribType)
    2867 +        {
    2868 +            case AnimationElement.AT_CSS:
    2869 +                attr = parent.getStyleAbsolute(attribName);
    2870 +                retVal = attr.getDoubleValue();
    2871 +                break;
    2872 +            case AnimationElement.AT_XML:
    2873 +                attr = parent.getPresAbsolute(attribName);
    2874 +                retVal = attr.getDoubleValue();
    2875 +                break;
    2876 +            case AnimationElement.AT_AUTO:
    2877 +                attr = parent.getStyleAbsolute(attribName);
    2878 +                if (attr == null) attr = parent.getPresAbsolute(attribName);
    2879 +                retVal = attr.getDoubleValue();
    2880 +                break;
    2881 +        }
    2882 +       
    2883 +       
    2884 +       
    2885 +        AnimationTimeEval state = new AnimationTimeEval();
    2886 +//        boolean pastEnd = true;
    2887 +
    2888 +        for (Iterator it = animEvents.iterator(); it.hasNext();)
    2889 +        {
    2890 +            Animate ele = (Animate)it.next();
    2891 +            ele.evalParametric(state, curTime);
    2892 +
    2893 +            //Go to next element if this one does not affect processing
    2894 +            if (Double.isNaN(state.interp)) continue;
    2895 +
    2896 +            switch (ele.getAdditiveType())
    2897 +            {
    2898 +                case AnimationElement.AD_SUM:
    2899 +                    retVal += ele.eval(state.interp);
    2900 +                    break;
    2901 +                case AnimationElement.AD_REPLACE:
    2902 +                    retVal = ele.eval(state.interp);
    2903 +                    break;
    2904 +            }
    2905 +           
    2906 +            //Evalutae accumulation if applicable
    2907 +            if (state.rep > 0)
    2908 +            {
    2909 +                switch (ele.getAccumulateType())
    2910 +                {
    2911 +                    case AnimationElement.AC_SUM:
    2912 +                        retVal += ele.repeatSkipSize(state.rep);
    2913 +                        break;
    2914 +                }
    2915 +               
    2916 +            }
    2917 +        }
    2918 +
    2919 +        return retVal;
    2920 +    }
    2921 +}
    2922 Index: core/src/com/kitfox/svg/animation/TrackManager.java
    2923 ===================================================================
    2924 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    2925 +++ core/src/com/kitfox/svg/animation/TrackManager.java 2012-06-17 23:56:57.684545050 +0200
    2926 @@ -0,0 +1,153 @@
    2927 +/*
    2928 + * TrackManager.java
    2929 + *
    2930 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    2931 + *  Copyright (C) 2004 Mark McKay
    2932 + *
    2933 + *  This library is free software; you can redistribute it and/or
    2934 + *  modify it under the terms of the GNU Lesser General Public
    2935 + *  License as published by the Free Software Foundation; either
    2936 + *  version 2.1 of the License, or (at your option) any later version.
    2937 + *
    2938 + *  This library is distributed in the hope that it will be useful,
    2939 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2940 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    2941 + *  Lesser General Public License for more details.
    2942 + *
    2943 + *  You should have received a copy of the GNU Lesser General Public
    2944 + *  License along with this library; if not, write to the Free Software
    2945 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    2946 + *
    2947 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    2948 + *  projects can be found at http://www.kitfox.com
    2949 + *
    2950 + * Created on August 15, 2004, 11:34 PM
    2951 + */
    2952 +
    2953 +package com.kitfox.svg.animation;
    2954 +
    2955 +import java.util.*;
    2956 +
    2957 +import com.kitfox.svg.*;
    2958 +import java.io.Serializable;
    2959 +
    2960 +/**
    2961 + * Every element contains tracks, which manage the animation.  There is one track
    2962 + * for every parameter with animation, and each track in turn is composed of
    2963 + * many events.
    2964 + *
    2965 + * @author Mark McKay
    2966 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    2967 + */
    2968 +public class TrackManager implements Serializable
    2969 +{
    2970 +    public static final long serialVersionUID = 0;
    2971 +   
    2972 +    static class TrackKey
    2973 +    {
    2974 +        String name;
    2975 +        int type;
    2976 +       
    2977 +        TrackKey(AnimationElement base)
    2978 +        {
    2979 +            this(base.getAttribName(), base.getAttribType());
    2980 +        }
    2981 +       
    2982 +        TrackKey(String name, int type)
    2983 +        {
    2984 +            this.name = name;
    2985 +            this.type = type;
    2986 +        }
    2987 +       
    2988 +        public int hashCode() { return name.hashCode() ^ type; }
    2989 +        public boolean equals(Object obj)
    2990 +        {
    2991 +            if (!(obj instanceof TrackKey)) return false;
    2992 +            TrackKey key = (TrackKey)obj;
    2993 +            return key.type == type && key.name.equals(name);
    2994 +        }
    2995 +    }
    2996 +   
    2997 +    HashMap tracks = new HashMap();
    2998 +   
    2999 +    /** Creates a new instance of TrackManager */
    3000 +    public TrackManager()
    3001 +    {
    3002 +    }
    3003 +   
    3004 +    /**
    3005 +     * Adds a new animation element to this track
    3006 +     */
    3007 +    public void addTrackElement(AnimationElement element) throws SVGElementException
    3008 +    {
    3009 +        TrackKey key = new TrackKey(element);
    3010 +       
    3011 +        TrackBase track = (TrackBase)tracks.get(key);
    3012 +       
    3013 +        if (track == null)
    3014 +        {
    3015 +            //Create a track for this element
    3016 +            if (element instanceof Animate)
    3017 +            {
    3018 +                switch (((Animate)element).getDataType())
    3019 +                {
    3020 +                    case Animate.DT_REAL:
    3021 +                        track = new TrackDouble(element);
    3022 +                        break;
    3023 +                    case Animate.DT_COLOR:
    3024 +                        track = new TrackColor(element);
    3025 +                        break;
    3026 +                    case Animate.DT_PATH:
    3027 +                        track = new TrackPath(element);
    3028 +                        break;
    3029 +                    default:
    3030 +                        throw new RuntimeException("");
    3031 +                }
    3032 +            }
    3033 +            else if (element instanceof AnimateColor)
    3034 +            {
    3035 +                track = new TrackColor(element);
    3036 +            }
    3037 +            else if (element instanceof AnimateTransform || element instanceof AnimateMotion)
    3038 +            {
    3039 +                track = new TrackTransform(element);
    3040 +            }
    3041 +           
    3042 +            tracks.put(key, track);
    3043 +        }
    3044 
    3045 +        track.addElement(element);
    3046 +    }
    3047 +   
    3048 +    public TrackBase getTrack(String name, int type)
    3049 +    {
    3050 +        //Handle AUTO, which will match either CSS or XML (in that order)
    3051 +        if (type == AnimationElement.AT_AUTO)
    3052 +        {
    3053 +            TrackBase t = getTrack(name, AnimationElement.AT_CSS);
    3054 +            if (t != null) return t;
    3055 +            t = getTrack(name, AnimationElement.AT_XML);
    3056 +            if (t != null) return t;
    3057 +            return null;
    3058 +        }
    3059 +       
    3060 +        //Get requested attribute
    3061 +        TrackKey key = new TrackKey(name, type);
    3062 +        TrackBase t = (TrackBase)tracks.get(key);
    3063 +        if (t != null) return t;
    3064 +       
    3065 +        //If that didn't exist, see if one exists of type AUTO
    3066 +        key = new TrackKey(name, AnimationElement.AT_AUTO);
    3067 +        return (TrackBase)tracks.get(key);
    3068 +    }
    3069 +   
    3070 +    public int getNumTracks()
    3071 +    {
    3072 +        return tracks.size();
    3073 +    }
    3074 +   
    3075 +    public Iterator iterator()
    3076 +    {
    3077 +        return tracks.values().iterator();
    3078 +    }
    3079 +}
    3080 Index: core/src/com/kitfox/svg/animation/TrackMotion.java
    3081 ===================================================================
    3082 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    3083 +++ core/src/com/kitfox/svg/animation/TrackMotion.java  2012-06-17 23:56:57.684545050 +0200
    3084 @@ -0,0 +1,128 @@
    3085 +/*
    3086 + * TrackManager.java
    3087 + *
    3088 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    3089 + *  Copyright (C) 2004 Mark McKay
    3090 + *
    3091 + *  This library is free software; you can redistribute it and/or
    3092 + *  modify it under the terms of the GNU Lesser General Public
    3093 + *  License as published by the Free Software Foundation; either
    3094 + *  version 2.1 of the License, or (at your option) any later version.
    3095 + *
    3096 + *  This library is distributed in the hope that it will be useful,
    3097 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    3098 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    3099 + *  Lesser General Public License for more details.
    3100 + *
    3101 + *  You should have received a copy of the GNU Lesser General Public
    3102 + *  License along with this library; if not, write to the Free Software
    3103 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    3104 + *
    3105 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    3106 + *  projects can be found at http://www.kitfox.com
    3107 + *
    3108 + * Created on September 21, 2004, 11:34 PM
    3109 + */
    3110 +
    3111 +package com.kitfox.svg.animation;
    3112 +
    3113 +import com.kitfox.svg.xml.StyleAttribute;
    3114 +import java.awt.geom.*;
    3115 +import java.util.*;
    3116 +
    3117 +import com.kitfox.svg.*;
    3118 +import com.kitfox.svg.xml.*;
    3119 +
    3120 +/**
    3121 + * A track holds the animation events for a single parameter of a single SVG
    3122 + * element.  It also contains the default value for the element, should the
    3123 + * user want to see the 'unanimated' value.
    3124 + *
    3125 + * @author Mark McKay
    3126 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    3127 + */
    3128 +public class TrackMotion extends TrackBase
    3129 +{
    3130 +    public TrackMotion(AnimationElement ele) throws SVGElementException
    3131 +    {
    3132 +        //The motion element implies a CSS attribute of transform
    3133 +//        super(ele.getParent(), "transform", AnimationElement.AT_CSS);
    3134 +        super(ele.getParent(), ele);
    3135 +    }
    3136 +
    3137 +    public boolean getValue(StyleAttribute attrib, double curTime) throws SVGException
    3138 +    {
    3139 +        AffineTransform retVal = new AffineTransform();
    3140 +        retVal = getValue(retVal, curTime);
    3141 +//        AffineTransform val = getValue(curTime);
    3142 +//        if (val == null) return false;
    3143 +
    3144 +        double[] mat = new double[6];
    3145 +        retVal.getMatrix(mat);
    3146 +        attrib.setStringValue("matrix(" + mat[0] + " " + mat[1] + " " + mat[2] + " " + mat[3] + " " + mat[4] + " " + mat[5] + ")");
    3147 +        return true;
    3148 +    }
    3149 +
    3150 +    public AffineTransform getValue(AffineTransform retVal, double curTime) throws SVGException
    3151 +    {
    3152 +        //Init transform with default state
    3153 +        StyleAttribute attr = null;
    3154 +        switch (attribType)
    3155 +        {
    3156 +            case AnimationElement.AT_CSS:
    3157 +                attr = parent.getStyleAbsolute(attribName);
    3158 +                retVal.setTransform(SVGElement.parseSingleTransform(attr.getStringValue()));
    3159 +                break;
    3160 +            case AnimationElement.AT_XML:
    3161 +                attr = parent.getPresAbsolute(attribName);
    3162 +                retVal.setTransform(SVGElement.parseSingleTransform(attr.getStringValue()));
    3163 +                break;
    3164 +            case AnimationElement.AT_AUTO:
    3165 +                attr = parent.getStyleAbsolute(attribName);
    3166 +                if (attr == null) attr = parent.getPresAbsolute(attribName);
    3167 +                retVal.setTransform(SVGElement.parseSingleTransform(attr.getStringValue()));
    3168 +                break;
    3169 +        }
    3170 +
    3171 +
    3172 +        //Update transform with time based information
    3173 +        AnimationTimeEval state = new AnimationTimeEval();
    3174 +        AffineTransform xform = new AffineTransform();
    3175 +//        boolean pastEnd = true;
    3176 +
    3177 +        for (Iterator it = animEvents.iterator(); it.hasNext();)
    3178 +        {
    3179 +            AnimateMotion ele = (AnimateMotion)it.next();
    3180 +            ele.evalParametric(state, curTime);
    3181 +
    3182 +            //Go to next element if this one does not affect processing
    3183 +            if (Double.isNaN(state.interp)) continue;
    3184 +
    3185 +            switch (ele.getAdditiveType())
    3186 +            {
    3187 +                case AnimationElement.AD_SUM:
    3188 +                    retVal.concatenate(ele.eval(xform, state.interp));
    3189 +                    break;
    3190 +                case AnimationElement.AD_REPLACE:
    3191 +                    retVal.setTransform(ele.eval(xform, state.interp));
    3192 +                    break;
    3193 +            }
    3194 +
    3195 +            //Evaluate accumulation if applicable
    3196 +/*
    3197 +            if (state.rep > 0)
    3198 +            {
    3199 +                switch (ele.getAccumulateType())
    3200 +                {
    3201 +                    case AnimationElement.AC_SUM:
    3202 +                        retVal += ele.repeatSkipSize(state.rep);
    3203 +                        break;
    3204 +                }
    3205 +
    3206 +            }
    3207 +*/
    3208 +        }
    3209 +
    3210 +        return retVal;
    3211 +    }
    3212 +}
    3213 Index: core/src/com/kitfox/svg/animation/TrackPath.java
    3214 ===================================================================
    3215 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    3216 +++ core/src/com/kitfox/svg/animation/TrackPath.java    2012-06-17 23:56:57.684545050 +0200
    3217 @@ -0,0 +1,100 @@
    3218 +/*
    3219 + * TrackManager.java
    3220 + *
    3221 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    3222 + *  Copyright (C) 2004 Mark McKay
    3223 + *
    3224 + *  This library is free software; you can redistribute it and/or
    3225 + *  modify it under the terms of the GNU Lesser General Public
    3226 + *  License as published by the Free Software Foundation; either
    3227 + *  version 2.1 of the License, or (at your option) any later version.
    3228 + *
    3229 + *  This library is distributed in the hope that it will be useful,
    3230 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    3231 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    3232 + *  Lesser General Public License for more details.
    3233 + *
    3234 + *  You should have received a copy of the GNU Lesser General Public
    3235 + *  License along with this library; if not, write to the Free Software
    3236 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    3237 + *
    3238 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    3239 + *  projects can be found at http://www.kitfox.com
    3240 + *
    3241 + * Created on September 21, 2004, 11:34 PM
    3242 + */
    3243 +
    3244 +package com.kitfox.svg.animation;
    3245 +
    3246 +import com.kitfox.svg.xml.StyleAttribute;
    3247 +import java.awt.*;
    3248 +import java.awt.geom.*;
    3249 +import java.util.*;
    3250 +
    3251 +import com.kitfox.svg.pathcmd.*;
    3252 +import com.kitfox.svg.*;
    3253 +import com.kitfox.svg.xml.*;
    3254 +
    3255 +/**
    3256 + * A track holds the animation events for a single parameter of a single SVG
    3257 + * element.  It also contains the default value for the element, should the
    3258 + * user want to see the 'unanimated' value.
    3259 + *
    3260 + * @author Mark McKay
    3261 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    3262 + */
    3263 +public class TrackPath extends TrackBase
    3264 +{
    3265 +
    3266 +    public TrackPath(AnimationElement ele) throws SVGElementException
    3267 +    {
    3268 +        super(ele.getParent(), ele);
    3269 +    }
    3270 +
    3271 +    public boolean getValue(StyleAttribute attrib, double curTime)
    3272 +    {
    3273 +        GeneralPath path = getValue(curTime);
    3274 +        if (path == null) return false;
    3275 +
    3276 +        attrib.setStringValue(PathUtil.buildPathString(path));
    3277 +        return true;
    3278 +    }
    3279 +
    3280 +    public GeneralPath getValue(double curTime)
    3281 +    {
    3282 +        GeneralPath retVal = null;
    3283 +        AnimationTimeEval state = new AnimationTimeEval();
    3284 +
    3285 +        for (Iterator it = animEvents.iterator(); it.hasNext();)
    3286 +        {
    3287 +            AnimateBase ele = (AnimateBase)it.next();
    3288 +            Animate eleAnim = (Animate)ele;
    3289 +            ele.evalParametric(state, curTime);
    3290 +
    3291 +            //Reject value if it is in the invalid state
    3292 +            if (Double.isNaN(state.interp)) continue;
    3293 +
    3294 +            if (retVal == null)
    3295 +            {
    3296 +                retVal = eleAnim.evalPath(state.interp);
    3297 +                continue;
    3298 +            }
    3299 +           
    3300 +            GeneralPath curPath = eleAnim.evalPath(state.interp);
    3301 +            switch (ele.getAdditiveType())
    3302 +            {
    3303 +                case AnimationElement.AD_REPLACE:
    3304 +                    retVal = curPath;
    3305 +                    break;
    3306 +                case AnimationElement.AD_SUM:
    3307 +                    throw new RuntimeException("Not implemented");
    3308 +//                    retVal = new Color(curCol.getRed() + retVal.getRed(), curCol.getGreen() + retVal.getGreen(), curCol.getBlue() + retVal.getBlue());
    3309 +//                    break;
    3310 +                default:
    3311 +                    throw new RuntimeException();
    3312 +            }
    3313 +        }
    3314 +
    3315 +        return retVal;
    3316 +    }
    3317 +}
    3318 Index: core/src/com/kitfox/svg/animation/TrackTransform.java
    3319 ===================================================================
    3320 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    3321 +++ core/src/com/kitfox/svg/animation/TrackTransform.java       2012-06-17 23:56:57.684545050 +0200
    3322 @@ -0,0 +1,112 @@
    3323 +/*
    3324 + * TrackManager.java
    3325 + *
    3326 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    3327 + *  Copyright (C) 2004 Mark McKay
    3328 + *
    3329 + *  This library is free software; you can redistribute it and/or
    3330 + *  modify it under the terms of the GNU Lesser General Public
    3331 + *  License as published by the Free Software Foundation; either
    3332 + *  version 2.1 of the License, or (at your option) any later version.
    3333 + *
    3334 + *  This library is distributed in the hope that it will be useful,
    3335 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    3336 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    3337 + *  Lesser General Public License for more details.
    3338 + *
    3339 + *  You should have received a copy of the GNU Lesser General Public
    3340 + *  License along with this library; if not, write to the Free Software
    3341 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    3342 + *
    3343 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    3344 + *  projects can be found at http://www.kitfox.com
    3345 + *
    3346 + * Created on September 21, 2004, 11:34 PM
    3347 + */
    3348 +
    3349 +package com.kitfox.svg.animation;
    3350 +
    3351 +import com.kitfox.svg.xml.StyleAttribute;
    3352 +import java.awt.geom.*;
    3353 +import java.util.*;
    3354 +
    3355 +import com.kitfox.svg.*;
    3356 +import com.kitfox.svg.xml.*;
    3357 +
    3358 +/**
    3359 + * A track holds the animation events for a single parameter of a single SVG
    3360 + * element.  It also contains the default value for the element, should the
    3361 + * user want to see the 'unanimated' value.
    3362 + *
    3363 + * @author Mark McKay
    3364 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    3365 + */
    3366 +public class TrackTransform extends TrackBase
    3367 +{
    3368 +    public TrackTransform(AnimationElement ele) throws SVGElementException
    3369 +    {
    3370 +        super(ele.getParent(), ele);
    3371 +    }
    3372 +
    3373 +    public boolean getValue(StyleAttribute attrib, double curTime) throws SVGException
    3374 +    {
    3375 +        AffineTransform retVal = new AffineTransform();
    3376 +        retVal = getValue(retVal, curTime);
    3377 +//        AffineTransform val = getValue(curTime);
    3378 +//        if (val == null) return false;
    3379 +
    3380 +        double[] mat = new double[6];
    3381 +        retVal.getMatrix(mat);
    3382 +        attrib.setStringValue("matrix(" + mat[0] + " " + mat[1] + " " + mat[2] + " " + mat[3] + " " + mat[4] + " " + mat[5] + ")");
    3383 +        return true;
    3384 +    }
    3385 +
    3386 +    public AffineTransform getValue(AffineTransform retVal, double curTime) throws SVGException
    3387 +    {
    3388 +        //Init transform with default state
    3389 +        StyleAttribute attr = null;
    3390 +        switch (attribType)
    3391 +        {
    3392 +            case AnimationElement.AT_CSS:
    3393 +                attr = parent.getStyleAbsolute(attribName);
    3394 +                retVal.setTransform(SVGElement.parseSingleTransform(attr.getStringValue()));
    3395 +                break;
    3396 +            case AnimationElement.AT_XML:
    3397 +                attr = parent.getPresAbsolute(attribName);
    3398 +                retVal.setTransform(SVGElement.parseSingleTransform(attr.getStringValue()));
    3399 +                break;
    3400 +            case AnimationElement.AT_AUTO:
    3401 +                attr = parent.getStyleAbsolute(attribName);
    3402 +                if (attr == null) attr = parent.getPresAbsolute(attribName);
    3403 +                retVal.setTransform(SVGElement.parseSingleTransform(attr.getStringValue()));
    3404 +                break;
    3405 +        }
    3406 +
    3407 +
    3408 +        //Update transform with time based information
    3409 +        AnimationTimeEval state = new AnimationTimeEval();
    3410 +        AffineTransform xform = new AffineTransform();
    3411 +
    3412 +        for (Iterator it = animEvents.iterator(); it.hasNext();)
    3413 +        {
    3414 +            AnimateXform ele = (AnimateXform)it.next();
    3415 +            ele.evalParametric(state, curTime);
    3416 +
    3417 +            //Go to next element if this one does not affect processing
    3418 +            if (Double.isNaN(state.interp)) continue;
    3419 +
    3420 +            switch (ele.getAdditiveType())
    3421 +            {
    3422 +                case AnimationElement.AD_SUM:
    3423 +                    retVal.concatenate(ele.eval(xform, state.interp));
    3424 +                    break;
    3425 +                case AnimationElement.AD_REPLACE:
    3426 +                    retVal.setTransform(ele.eval(xform, state.interp));
    3427 +                    break;
    3428 +            }
    3429 +
    3430 +        }
    3431 +
    3432 +        return retVal;
    3433 +    }
    3434 +}
    3435 Index: core/src/com/kitfox/svg/SVGElement.java
    3436 ===================================================================
    3437 --- core.orig/src/com/kitfox/svg/SVGElement.java        2012-05-11 17:03:52.404311564 +0200
    3438 +++ core/src/com/kitfox/svg/SVGElement.java     2012-06-17 23:56:57.732545052 +0200
    3439 @@ -33,6 +33,7 @@
    3440  import java.awt.geom.*;
    3441  
    3442  import org.xml.sax.*;
    3443 +import com.kitfox.svg.animation.*;
    3444  import com.kitfox.svg.pathcmd.*;
    3445  import com.kitfox.svg.xml.*;
    3446  import java.io.Serializable;
    3447 @@ -100,6 +101,8 @@
     1Only in kitfox/svg: animation
     2Only in kitfox/svg/app/ant: SVGToImageAntTask.java
     3Only in kitfox/svg/app/beans: ProportionalLayoutPanel.form
     4Only in kitfox/svg/app/beans: ProportionalLayoutPanel.java
     5Only in kitfox/svg/app/beans: SVGPanel.form
     6Only in kitfox/svg/app/beans: SVGPanel.java
     7Only in kitfox/svg/app/data: HandlerFactory.java
     8Only in kitfox/svg/app: MainFrame.form
     9Only in kitfox/svg/app: MainFrame.java
     10Only in kitfox/svg/app: PlayerDialog.form
     11Only in kitfox/svg/app: PlayerDialog.java
     12Only in kitfox/svg/app: PlayerThread.java
     13Only in kitfox/svg/app: PlayerThreadListener.java
     14Only in kitfox/svg/app: SVGPlayer.form
     15Only in kitfox/svg/app: SVGPlayer.java
     16Only in kitfox/svg/app: SVGViewer.form
     17Only in kitfox/svg/app: SVGViewer.java
     18Only in kitfox/svg/app: VersionDialog.form
     19Only in kitfox/svg/app: VersionDialog.java
     20Only in kitfox/svg: SVGDisplayPanel.form
     21diff -ur kitfox/svg/SVGElement.java src/com/kitfox/svg/SVGElement.java
     22--- kitfox/svg/SVGElement.java  2014-10-30 11:31:46.229650244 +0100
     23+++ src/com/kitfox/svg/SVGElement.java  2014-10-29 23:30:19.882171106 +0100
     24@@ -35,9 +35,6 @@
     25  */
     26 package com.kitfox.svg;
     27 
     28-import com.kitfox.svg.animation.AnimationElement;
     29-import com.kitfox.svg.animation.TrackBase;
     30-import com.kitfox.svg.animation.TrackManager;
     31 import com.kitfox.svg.pathcmd.Arc;
     32 import com.kitfox.svg.pathcmd.BuildHistory;
     33 import com.kitfox.svg.pathcmd.Cubic;
     34@@ -122,10 +119,6 @@
     35      * The diagram this element belongs to
    344836      */
    3449  //    protected SVGUniverse universe;
    3450      
    3451 +    protected final TrackManager trackManager = new TrackManager();
    3452 +
     37     protected SVGDiagram diagram;
     38-    /**
     39-     * Link to the universe we reside in
     40-     */
     41-    protected final TrackManager trackManager = new TrackManager();
    345342     boolean dirty = true;
    345443 
    3455  //    public static final Matcher adobeId = Pattern.compile("(.*)_1_").matcher("");
    3456 @@ -265,6 +268,46 @@
     44     /**
     45@@ -305,65 +298,6 @@
    345746         }
    345847     }
    3459      
    3460 +    public void addAttribute(String name, int attribType, String value) throws SVGElementException
    3461 +    {
    3462 +        if (hasAttribute(name, attribType)) throw new SVGElementException(this, "Attribute " + name + "(" + AnimationElement.animationElementToString(attribType) + ") already exists");
    3463 +       
    3464 +        //Alter layout for id attribute
    3465 +        if ("id".equals(name) && diagram != null)
    3466 +        {
    3467 +            diagram.removeElement(this.id);
    3468 +            this.id = name;
    3469 +            diagram.setElement(this.id, this);
    3470 +        }
    3471 +       
    3472 +        switch (attribType)
    3473 +        {
    3474 +            case AnimationElement.AT_CSS:
    3475 +                inlineStyles.put(name, new StyleAttribute(name, value));
    3476 +                return;
    3477 +            case AnimationElement.AT_XML:
    3478 +                presAttribs.put(name, new StyleAttribute(name, value));
    3479 +                return;
    3480 +        }
    3481 +       
    3482 +        throw new SVGElementException(this, "Invalid attribute type " + attribType);
    3483 +    }
    3484 +   
    3485 +    public boolean hasAttribute(String name, int attribType) throws SVGElementException
    3486 +    {
    3487 +        switch (attribType)
    3488 +        {
    3489 +            case AnimationElement.AT_CSS:
    3490 +                return inlineStyles.containsKey(name);
    3491 +            case AnimationElement.AT_XML:
    3492 +                return presAttribs.containsKey(name);
    3493 +            case AnimationElement.AT_AUTO:
    3494 +                return inlineStyles.containsKey(name) || presAttribs.containsKey(name);
    3495 +        }
    3496 +       
    3497 +        throw new SVGElementException(this, "Invalid attribute type " + attribType);
    3498 +    }
    3499 +   
     48 
     49-    public void removeAttribute(String name, int attribType)
     50-    {
     51-        switch (attribType)
     52-        {
     53-            case AnimationElement.AT_CSS:
     54-                inlineStyles.remove(name);
     55-                return;
     56-            case AnimationElement.AT_XML:
     57-                presAttribs.remove(name);
     58-                return;
     59-        }
     60-    }
     61-
     62-    public void addAttribute(String name, int attribType, String value) throws SVGElementException
     63-    {
     64-        if (hasAttribute(name, attribType))
     65-        {
     66-            throw new SVGElementException(this, "Attribute " + name + "(" + AnimationElement.animationElementToString(attribType) + ") already exists");
     67-        }
     68-
     69-        //Alter layout for id attribute
     70-        if ("id".equals(name))
     71-        {
     72-            if (diagram != null)
     73-            {
     74-                diagram.removeElement(id);
     75-                diagram.setElement(value, this);
     76-            }
     77-            this.id = value;
     78-        }
     79-
     80-        switch (attribType)
     81-        {
     82-            case AnimationElement.AT_CSS:
     83-                inlineStyles.put(name, new StyleAttribute(name, value));
     84-                return;
     85-            case AnimationElement.AT_XML:
     86-                presAttribs.put(name, new StyleAttribute(name, value));
     87-                return;
     88-        }
     89-
     90-        throw new SVGElementException(this, "Invalid attribute type " + attribType);
     91-    }
     92-
     93-    public boolean hasAttribute(String name, int attribType) throws SVGElementException
     94-    {
     95-        switch (attribType)
     96-        {
     97-            case AnimationElement.AT_CSS:
     98-                return inlineStyles.containsKey(name);
     99-            case AnimationElement.AT_XML:
     100-                return presAttribs.containsKey(name);
     101-            case AnimationElement.AT_AUTO:
     102-                return inlineStyles.containsKey(name) || presAttribs.containsKey(name);
     103-        }
     104-
     105-        throw new SVGElementException(this, "Invalid attribute type " + attribType);
     106-    }
     107-
    3500108     /**
    3501109      * @return a set of Strings that corespond to CSS attributes on this element
    3502110      */
    3503 @@ -290,6 +333,12 @@
     111@@ -389,12 +323,6 @@
    3504112         children.add(child);
    3505113         child.parent = this;
    3506114         child.setDiagram(diagram);
    3507 +       
    3508 +        //Add info to track if we've scanned animation element
    3509 +        if (child instanceof AnimationElement)
    3510 +        {
    3511 +            trackManager.addTrackElement((AnimationElement)child);
    3512 +        }
     115-
     116-        //Add info to track if we've scanned animation element
     117-        if (child instanceof AnimationElement)
     118-        {
     119-            trackManager.addTrackElement((AnimationElement) child);
     120-        }
    3513121     }
    3514     
    3515      private void setDiagram(SVGDiagram diagram)
    3516 @@ -408,6 +457,54 @@
     122 
     123     protected void setDiagram(SVGDiagram diagram)
     124@@ -529,61 +457,6 @@
    3517125         return getStyle(attrib, true);
    3518126     }
    3519      
    3520 +   
    3521 +    public void setAttribute(String name, int attribType, String value) throws SVGElementException
    3522 +    {
    3523 +        StyleAttribute styAttr;
    3524 +       
    3525 +       
    3526 +        switch (attribType)
    3527 +        {
    3528 +            case AnimationElement.AT_CSS:
    3529 +            {
    3530 +                styAttr = (StyleAttribute)inlineStyles.get(name);
    3531 +                break;
    3532 +            }
    3533 +            case AnimationElement.AT_XML:
    3534 +            {
    3535 +                styAttr = (StyleAttribute)presAttribs.get(name);
    3536 +                break;
    3537 +            }
    3538 +            case AnimationElement.AT_AUTO:
    3539 +            {
    3540 +                styAttr = (StyleAttribute)inlineStyles.get(name);
    3541 +               
    3542 +                if (styAttr == null)
    3543 +                {
    3544 +                    styAttr = (StyleAttribute)presAttribs.get(name);
    3545 +                }
    3546 +                break;
    3547 +            }
    3548 +            default:
    3549 +                throw new SVGElementException(this, "Invalid attribute type " + attribType);
    3550 +        }
    3551 +       
    3552 +        if (styAttr == null)
    3553 +        {
    3554 +            throw new SVGElementException(this, "Could not find attribute " + name + "(" + AnimationElement.animationElementToString(attribType) + ").  Make sure to create attribute before setting it.");
    3555 +        }
    3556 +       
    3557 +        //Alter layout for relevant attributes
    3558 +        if ("id".equals(styAttr.getName()))
    3559 +        {
    3560 +            diagram.removeElement(this.id);
    3561 +            this.id = name;
    3562 +            diagram.setElement(this.id, this);
    3563 +        }
    3564 +       
    3565 +        styAttr.setStringValue(value);
    3566 +    }
    3567 +   
     127 
     128-    public void setAttribute(String name, int attribType, String value) throws SVGElementException
     129-    {
     130-        StyleAttribute styAttr;
     131-
     132-
     133-        switch (attribType)
     134-        {
     135-            case AnimationElement.AT_CSS:
     136-            {
     137-                styAttr = (StyleAttribute) inlineStyles.get(name);
     138-                break;
     139-            }
     140-            case AnimationElement.AT_XML:
     141-            {
     142-                styAttr = (StyleAttribute) presAttribs.get(name);
     143-                break;
     144-            }
     145-            case AnimationElement.AT_AUTO:
     146-            {
     147-                styAttr = (StyleAttribute) inlineStyles.get(name);
     148-
     149-                if (styAttr == null)
     150-                {
     151-                    styAttr = (StyleAttribute) presAttribs.get(name);
     152-                }
     153-                break;
     154-            }
     155-            default:
     156-                throw new SVGElementException(this, "Invalid attribute type " + attribType);
     157-        }
     158-
     159-        if (styAttr == null)
     160-        {
     161-            throw new SVGElementException(this, "Could not find attribute " + name + "(" + AnimationElement.animationElementToString(attribType) + ").  Make sure to create attribute before setting it.");
     162-        }
     163-
     164-        //Alter layout for relevant attributes
     165-        if ("id".equals(styAttr.getName()))
     166-        {
     167-            if (diagram != null)
     168-            {
     169-                diagram.removeElement(this.id);
     170-                diagram.setElement(value, this);
     171-            }
     172-            this.id = value;
     173-        }
     174-
     175-        styAttr.setStringValue(value);
     176-    }
     177-
     178-    public boolean getStyle(StyleAttribute attrib, boolean recursive) throws SVGException
     179-    {
     180-        return getStyle(attrib, recursive, true);
     181-    }
     182-   
    3568183     /**
    3569       * Copies the current style into the passed style attribute.  Checks for
    3570       * inline styles first, then internal and extranal style sheets, and
    3571 @@ -427,6 +524,14 @@
    3572          
     184      * Copies the current style into the passed style attribute. Checks for
     185      * inline styles first, then internal and extranal style sheets, and finally
     186@@ -595,8 +468,7 @@
     187      * style attribute, checks attributes of parents back to root until one
     188      * found.
     189      */
     190-    public boolean getStyle(StyleAttribute attrib, boolean recursive, boolean evalAnimation)
     191-            throws SVGException
     192+    public boolean getStyle(StyleAttribute attrib, boolean recursive) throws SVGException
     193     {
     194         String styName = attrib.getName();
     195 
     196@@ -605,17 +477,6 @@
     197 
    3573198         attrib.setStringValue(styAttr == null ? "" : styAttr.getStringValue());
    3574          
    3575 +        //Evalutate coresponding track, if one exists
    3576 +        TrackBase track = trackManager.getTrack(styName, AnimationElement.AT_CSS);
    3577 +        if (track != null)
    3578 +        {
    3579 +            track.getValue(attrib, diagram.getUniverse().getCurTime());
    3580 +            return true;
    3581 +        }
    3582 +       
     199 
     200-        //Evalutate coresponding track, if one exists
     201-        if (evalAnimation)
     202-        {
     203-            TrackBase track = trackManager.getTrack(styName, AnimationElement.AT_CSS);
     204-            if (track != null)
     205-            {
     206-                track.getValue(attrib, diagram.getUniverse().getCurTime());
     207-                return true;
     208-            }
     209-        }
     210-
    3583211         //Return if we've found a non animated style
    3584          if (styAttr != null) return true;
    3585          
    3586 @@ -439,6 +544,14 @@
    3587         
     212         if (styAttr != null)
     213         {
     214@@ -628,17 +489,6 @@
     215 
    3588216         attrib.setStringValue(presAttr == null ? "" : presAttr.getStringValue());
    3589          
    3590 +        //Evalutate coresponding track, if one exists
    3591 +        track = trackManager.getTrack(styName, AnimationElement.AT_XML);
    3592 +        if (track != null)
    3593 +        {
    3594 +            track.getValue(attrib, diagram.getUniverse().getCurTime());
    3595 +            return true;
    3596 +        }
    3597 +       
     217 
     218-        //Evalutate coresponding track, if one exists
     219-        if (evalAnimation)
     220-        {
     221-            TrackBase track = trackManager.getTrack(styName, AnimationElement.AT_XML);
     222-            if (track != null)
     223-            {
     224-                track.getValue(attrib, diagram.getUniverse().getCurTime());
     225-                return true;
     226-            }
     227-        }
     228-
    3598229         //Return if we've found a presentation attribute instead
    3599          if (presAttr != null) return true;
    3600          
    3601 @@ -480,6 +593,14 @@
     230         if (presAttr != null)
     231         {
     232@@ -700,14 +550,6 @@
    3602233         //Copy presentation value directly
    3603234         attrib.setStringValue(presAttr == null ? "" : presAttr.getStringValue());
    3604         
    3605 +        //Evalutate coresponding track, if one exists
    3606 +        TrackBase track = trackManager.getTrack(presName, AnimationElement.AT_XML);
    3607 +        if (track != null)
    3608 +        {
    3609 +            track.getValue(attrib, diagram.getUniverse().getCurTime());
    3610 +            return true;
    3611 +        }
    3612 +       
     235 
     236-        //Evalutate coresponding track, if one exists
     237-        TrackBase track = trackManager.getTrack(presName, AnimationElement.AT_XML);
     238-        if (track != null)
     239-        {
     240-            track.getValue(attrib, diagram.getUniverse().getCurTime());
     241-            return true;
     242-        }
     243-
    3613244         //Return if we found presentation attribute
    3614          if (presAttr != null) return true;
    3615          
    3616 Index: core/src/com/kitfox/svg/SVGLoader.java
    3617 ===================================================================
    3618 --- core.orig/src/com/kitfox/svg/SVGLoader.java 2012-05-11 17:03:52.404311564 +0200
    3619 +++ core/src/com/kitfox/svg/SVGLoader.java      2012-06-17 23:56:57.732545052 +0200
    3620 @@ -33,6 +33,8 @@
     245         if (presAttr != null)
     246         {
     247diff -ur kitfox/svg/SVGLoaderHelper.java src/com/kitfox/svg/SVGLoaderHelper.java
     248--- kitfox/svg/SVGLoaderHelper.java     2014-10-29 22:49:38.193473772 +0100
     249+++ src/com/kitfox/svg/SVGLoaderHelper.java     2014-10-29 22:54:17.671385584 +0100
     250@@ -37,9 +37,6 @@
     251 package com.kitfox.svg;
     252 
     253 import java.net.*;
     254-import java.io.*;
     255-
     256-import com.kitfox.svg.animation.parser.*;
     257 
     258 /**
     259  * @author Mark McKay
     260@@ -58,11 +55,6 @@
     261     public final SVGDiagram diagram;
     262 
     263     public final URI xmlBase;
     264-
     265-    /**
     266-     * Animate nodes use this to parse their time strings
     267-     */
     268-    public final AnimTimeParser animTimeParser = new AnimTimeParser(new StringReader(""));
     269     
     270     /** Creates a new instance of SVGLoaderHelper */
     271     public SVGLoaderHelper(URI xmlBase, SVGUniverse universe, SVGDiagram diagram)
     272diff -ur kitfox/svg/SVGLoader.java src/com/kitfox/svg/SVGLoader.java
     273--- kitfox/svg/SVGLoader.java   2014-10-29 22:49:38.193473772 +0100
     274+++ src/com/kitfox/svg/SVGLoader.java   2014-10-29 22:53:56.462392128 +0100
     275@@ -42,7 +42,6 @@
    3621276 import org.xml.sax.*;
    3622277 import org.xml.sax.helpers.DefaultHandler;
    3623278 
    3624 +import com.kitfox.svg.animation.*;
    3625 +
    3626  /**
    3627   * @author Mark McKay
    3628   * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    3629 @@ -75,6 +77,10 @@
     279-import com.kitfox.svg.animation.*;
     280 import java.util.logging.Level;
     281 import java.util.logging.Logger;
     282 
     283@@ -88,10 +87,6 @@
    3630284 
    3631285         //Compile a list of important builder classes
    3632286         nodeClasses.put("a", A.class);
    3633 +        nodeClasses.put("animate", Animate.class);
    3634 +        nodeClasses.put("animatecolor", AnimateColor.class);
    3635 +        nodeClasses.put("animatemotion", AnimateMotion.class);
    3636 +        nodeClasses.put("animatetransform", AnimateTransform.class);
     287-        nodeClasses.put("animate", Animate.class);
     288-        nodeClasses.put("animatecolor", AnimateColor.class);
     289-        nodeClasses.put("animatemotion", AnimateMotion.class);
     290-        nodeClasses.put("animatetransform", AnimateTransform.class);
    3637291         nodeClasses.put("circle", Circle.class);
    3638292         nodeClasses.put("clippath", ClipPath.class);
    3639293         nodeClasses.put("defs", Defs.class);
    3640 @@ -98,6 +104,7 @@
     294@@ -115,7 +110,6 @@
    3641295         nodeClasses.put("polyline", Polyline.class);
    3642296         nodeClasses.put("radialgradient", RadialGradient.class);
    3643297         nodeClasses.put("rect", Rect.class);
    3644 +        nodeClasses.put("set", SetSmil.class);
     298-        nodeClasses.put("set", SetSmil.class);
    3645299         nodeClasses.put("shape", ShapeElement.class);
    3646300         nodeClasses.put("stop", Stop.class);
    3647301         nodeClasses.put("style", Style.class);
    3648 Index: core/src/com/kitfox/svg/SVGLoaderHelper.java
    3649 ===================================================================
    3650 --- core.orig/src/com/kitfox/svg/SVGLoaderHelper.java   2012-05-11 17:03:52.404311564 +0200
    3651 +++ core/src/com/kitfox/svg/SVGLoaderHelper.java        2012-06-17 23:56:57.740545051 +0200
    3652 @@ -28,6 +28,9 @@
    3653  package com.kitfox.svg;
    3654  
    3655  import java.net.*;
    3656 +import java.io.*;
    3657 +
    3658 +import com.kitfox.svg.animation.parser.*;
    3659  
    3660  /**
    3661   * @author Mark McKay
    3662 @@ -47,6 +50,11 @@
    3663  
    3664      public final URI xmlBase;
    3665  
    3666 +    /**
    3667 +     * Animate nodes use this to parse their time strings
    3668 +     */
    3669 +    public final AnimTimeParser animTimeParser = new AnimTimeParser(new StringReader(""));
    3670 +   
    3671      /** Creates a new instance of SVGLoaderHelper */
    3672      public SVGLoaderHelper(URI xmlBase, SVGUniverse universe, SVGDiagram diagram)
    3673      {
    3674 Index: core/src/com/kitfox/svg/app/MainFrame.java
    3675 ===================================================================
    3676 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    3677 +++ core/src/com/kitfox/svg/app/MainFrame.java  2012-06-17 23:56:57.748545052 +0200
    3678 @@ -0,0 +1,134 @@
    3679 +/*
    3680 + * MainFrame.java
    3681 + *
    3682 + * Created on September 6, 2004, 1:19 AM
    3683 + */
    3684 +
    3685 +package com.kitfox.svg.app;
    3686 +
    3687 +/**
    3688 + *
    3689 + * @author  kitfox
    3690 + */
    3691 +public class MainFrame extends javax.swing.JFrame
    3692 +{
    3693 +    public static final long serialVersionUID = 1;
    3694 +   
    3695 +    /** Creates new form MainFrame */
    3696 +    public MainFrame()
    3697 +    {
    3698 +        initComponents();
    3699 +    }
    3700 +   
    3701 +    /** This method is called from within the constructor to
    3702 +     * initialize the form.
    3703 +     * WARNING: Do NOT modify this code. The content of this method is
    3704 +     * always regenerated by the Form Editor.
    3705 +     */
    3706 +    private void initComponents()//GEN-BEGIN:initComponents
    3707 +    {
    3708 +        jPanel1 = new javax.swing.JPanel();
    3709 +        bn_svgViewer = new javax.swing.JButton();
    3710 +        bn_svgViewer1 = new javax.swing.JButton();
    3711 +        jPanel2 = new javax.swing.JPanel();
    3712 +        bn_quit = new javax.swing.JButton();
    3713 +
    3714 +        setTitle("SVG Salamander - Application Launcher");
    3715 +        addWindowListener(new java.awt.event.WindowAdapter()
    3716 +        {
    3717 +            public void windowClosing(java.awt.event.WindowEvent evt)
    3718 +            {
    3719 +                exitForm(evt);
    3720 +            }
    3721 +        });
    3722 +
    3723 +        jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.Y_AXIS));
    3724 +
    3725 +        bn_svgViewer.setText("SVG Viewer (No animation)");
    3726 +        bn_svgViewer.addActionListener(new java.awt.event.ActionListener()
    3727 +        {
    3728 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    3729 +            {
    3730 +                bn_svgViewerActionPerformed(evt);
    3731 +            }
    3732 +        });
    3733 +
    3734 +        jPanel1.add(bn_svgViewer);
    3735 +
    3736 +        bn_svgViewer1.setText("SVG Player (Animation)");
    3737 +        bn_svgViewer1.addActionListener(new java.awt.event.ActionListener()
    3738 +        {
    3739 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    3740 +            {
    3741 +                bn_svgViewer1ActionPerformed(evt);
    3742 +            }
    3743 +        });
    3744 +
    3745 +        jPanel1.add(bn_svgViewer1);
    3746 +
    3747 +        getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
    3748 +
    3749 +        bn_quit.setText("Quit");
    3750 +        bn_quit.addActionListener(new java.awt.event.ActionListener()
    3751 +        {
    3752 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    3753 +            {
    3754 +                bn_quitActionPerformed(evt);
    3755 +            }
    3756 +        });
    3757 +
    3758 +        jPanel2.add(bn_quit);
    3759 +
    3760 +        getContentPane().add(jPanel2, java.awt.BorderLayout.SOUTH);
    3761 +
    3762 +        pack();
    3763 +    }//GEN-END:initComponents
    3764 +
    3765 +    private void bn_svgViewer1ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_svgViewer1ActionPerformed
    3766 +    {//GEN-HEADEREND:event_bn_svgViewer1ActionPerformed
    3767 +        SVGPlayer.main(null);
    3768 +
    3769 +        close();
    3770 +    }//GEN-LAST:event_bn_svgViewer1ActionPerformed
    3771 +
    3772 +    private void bn_svgViewerActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_svgViewerActionPerformed
    3773 +    {//GEN-HEADEREND:event_bn_svgViewerActionPerformed
    3774 +        SVGViewer.main(null);
    3775 +
    3776 +        close();
    3777 +    }//GEN-LAST:event_bn_svgViewerActionPerformed
    3778 +
    3779 +    private void bn_quitActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_quitActionPerformed
    3780 +    {//GEN-HEADEREND:event_bn_quitActionPerformed
    3781 +        exitForm(null);
    3782 +    }//GEN-LAST:event_bn_quitActionPerformed
    3783 +   
    3784 +    /** Exit the Application */
    3785 +    private void exitForm(java.awt.event.WindowEvent evt)//GEN-FIRST:event_exitForm
    3786 +    {
    3787 +        System.exit(0);
    3788 +    }//GEN-LAST:event_exitForm
    3789 +   
    3790 +    private void close()
    3791 +    {
    3792 +        this.setVisible(false);
    3793 +        this.dispose();
    3794 +    }
    3795 +   
    3796 +    /**
    3797 +     * @param args the command line arguments
    3798 +     */
    3799 +    public static void main(String args[])
    3800 +    {
    3801 +        new MainFrame().setVisible(true);
    3802 +    }
    3803 +   
    3804 +    // Variables declaration - do not modify//GEN-BEGIN:variables
    3805 +    private javax.swing.JButton bn_quit;
    3806 +    private javax.swing.JButton bn_svgViewer;
    3807 +    private javax.swing.JButton bn_svgViewer1;
    3808 +    private javax.swing.JPanel jPanel1;
    3809 +    private javax.swing.JPanel jPanel2;
    3810 +    // End of variables declaration//GEN-END:variables
    3811 +   
    3812 +}
    3813 Index: core/src/com/kitfox/svg/app/PlayerDialog.java
    3814 ===================================================================
    3815 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    3816 +++ core/src/com/kitfox/svg/app/PlayerDialog.java       2012-06-17 23:56:57.748545052 +0200
    3817 @@ -0,0 +1,289 @@
    3818 +/*
    3819 + * PlayerDialog.java
    3820 + *
    3821 + *
    3822 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    3823 + *  Copyright (C) 2004 Mark McKay
    3824 + *
    3825 + *  This library is free software; you can redistribute it and/or
    3826 + *  modify it under the terms of the GNU Lesser General Public
    3827 + *  License as published by the Free Software Foundation; either
    3828 + *  version 2.1 of the License, or (at your option) any later version.
    3829 + *
    3830 + *  This library is distributed in the hope that it will be useful,
    3831 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    3832 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    3833 + *  Lesser General Public License for more details.
    3834 + *
    3835 + *  You should have received a copy of the GNU Lesser General Public
    3836 + *  License along with this library; if not, write to the Free Software
    3837 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    3838 + *
    3839 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    3840 + *  projects can be found at http://www.kitfox.com
    3841 + *
    3842 + * Created on September 28, 2004, 9:56 PM
    3843 + */
    3844 +
    3845 +package com.kitfox.svg.app;
    3846 +
    3847 +/**
    3848 + *
    3849 + * @author  kitfox
    3850 + */
    3851 +public class PlayerDialog extends javax.swing.JDialog implements PlayerThreadListener
    3852 +{
    3853 +    public static final long serialVersionUID = 1;
    3854 +   
    3855 +    PlayerThread thread;
    3856 +   
    3857 +    final SVGPlayer parent;
    3858 +   
    3859 +    /** Creates new form PlayerDialog */
    3860 +    public PlayerDialog(SVGPlayer parent)
    3861 +    {
    3862 +        super(parent, false);
    3863 +        initComponents();
    3864 +       
    3865 +        this.parent = parent;
    3866 +       
    3867 +        thread = new PlayerThread();
    3868 +        thread.addListener(this);
    3869 +       
    3870 +        text_timeStepActionPerformed(null);
    3871 +    }
    3872 +   
    3873 +    public void updateTime(double curTime, double timeStep, int playState)
    3874 +    {
    3875 +        if (playState == PlayerThread.PS_STOP) return;
    3876 +       
    3877 +        text_curTime.setText("" + (float)curTime);
    3878 +        parent.updateTime(curTime);
    3879 +//        text_timeStep.setText("" + (int)(1.0 / timeStep));
    3880 +    }
    3881 +   
    3882 +    /** This method is called from within the constructor to
    3883 +     * initialize the form.
    3884 +     * WARNING: Do NOT modify this code. The content of this method is
    3885 +     * always regenerated by the Form Editor.
    3886 +     */
    3887 +    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    3888 +    private void initComponents()
    3889 +    {
    3890 +        jPanel1 = new javax.swing.JPanel();
    3891 +        bn_playBack = new javax.swing.JButton();
    3892 +        bn_stop = new javax.swing.JButton();
    3893 +        bn_playFwd = new javax.swing.JButton();
    3894 +        jPanel2 = new javax.swing.JPanel();
    3895 +        jPanel3 = new javax.swing.JPanel();
    3896 +        jLabel1 = new javax.swing.JLabel();
    3897 +        text_curTime = new javax.swing.JTextField();
    3898 +        bn_time0 = new javax.swing.JButton();
    3899 +        jPanel4 = new javax.swing.JPanel();
    3900 +        jLabel2 = new javax.swing.JLabel();
    3901 +        text_timeStep = new javax.swing.JTextField();
    3902 +
    3903 +        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
    3904 +        setTitle("Player");
    3905 +        addWindowListener(new java.awt.event.WindowAdapter()
    3906 +        {
    3907 +            public void windowClosed(java.awt.event.WindowEvent evt)
    3908 +            {
    3909 +                formWindowClosed(evt);
    3910 +            }
    3911 +        });
    3912 +
    3913 +        bn_playBack.setText("<");
    3914 +        bn_playBack.setToolTipText("Play backwards");
    3915 +        bn_playBack.addActionListener(new java.awt.event.ActionListener()
    3916 +        {
    3917 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    3918 +            {
    3919 +                bn_playBackActionPerformed(evt);
    3920 +            }
    3921 +        });
    3922 +
    3923 +        jPanel1.add(bn_playBack);
    3924 +
    3925 +        bn_stop.setText("||");
    3926 +        bn_stop.setToolTipText("Stop playback");
    3927 +        bn_stop.addActionListener(new java.awt.event.ActionListener()
    3928 +        {
    3929 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    3930 +            {
    3931 +                bn_stopActionPerformed(evt);
    3932 +            }
    3933 +        });
    3934 +
    3935 +        jPanel1.add(bn_stop);
    3936 +
    3937 +        bn_playFwd.setText(">");
    3938 +        bn_playFwd.setToolTipText("Play Forwards");
    3939 +        bn_playFwd.addActionListener(new java.awt.event.ActionListener()
    3940 +        {
    3941 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    3942 +            {
    3943 +                bn_playFwdActionPerformed(evt);
    3944 +            }
    3945 +        });
    3946 +
    3947 +        jPanel1.add(bn_playFwd);
    3948 +
    3949 +        getContentPane().add(jPanel1, java.awt.BorderLayout.NORTH);
    3950 +
    3951 +        jPanel2.setLayout(new javax.swing.BoxLayout(jPanel2, javax.swing.BoxLayout.Y_AXIS));
    3952 +
    3953 +        jLabel1.setText("Cur Time");
    3954 +        jPanel3.add(jLabel1);
    3955 +
    3956 +        text_curTime.setHorizontalAlignment(javax.swing.JTextField.LEFT);
    3957 +        text_curTime.setText("0");
    3958 +        text_curTime.setPreferredSize(new java.awt.Dimension(100, 21));
    3959 +        text_curTime.addActionListener(new java.awt.event.ActionListener()
    3960 +        {
    3961 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    3962 +            {
    3963 +                text_curTimeActionPerformed(evt);
    3964 +            }
    3965 +        });
    3966 +        text_curTime.addFocusListener(new java.awt.event.FocusAdapter()
    3967 +        {
    3968 +            public void focusLost(java.awt.event.FocusEvent evt)
    3969 +            {
    3970 +                text_curTimeFocusLost(evt);
    3971 +            }
    3972 +        });
    3973 +
    3974 +        jPanel3.add(text_curTime);
    3975 +
    3976 +        bn_time0.setText("Time 0");
    3977 +        bn_time0.setToolTipText("Reset time to first frame");
    3978 +        bn_time0.addActionListener(new java.awt.event.ActionListener()
    3979 +        {
    3980 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    3981 +            {
    3982 +                bn_time0ActionPerformed(evt);
    3983 +            }
    3984 +        });
    3985 +
    3986 +        jPanel3.add(bn_time0);
    3987 +
    3988 +        jPanel2.add(jPanel3);
    3989 +
    3990 +        jLabel2.setText("Frames Per Second");
    3991 +        jPanel4.add(jLabel2);
    3992 +
    3993 +        text_timeStep.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
    3994 +        text_timeStep.setText("60");
    3995 +        text_timeStep.setPreferredSize(new java.awt.Dimension(100, 21));
    3996 +        text_timeStep.addActionListener(new java.awt.event.ActionListener()
    3997 +        {
    3998 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    3999 +            {
    4000 +                text_timeStepActionPerformed(evt);
    4001 +            }
    4002 +        });
    4003 +        text_timeStep.addFocusListener(new java.awt.event.FocusAdapter()
    4004 +        {
    4005 +            public void focusLost(java.awt.event.FocusEvent evt)
    4006 +            {
    4007 +                text_timeStepFocusLost(evt);
    4008 +            }
    4009 +        });
    4010 +
    4011 +        jPanel4.add(text_timeStep);
    4012 +
    4013 +        jPanel2.add(jPanel4);
    4014 +
    4015 +        getContentPane().add(jPanel2, java.awt.BorderLayout.CENTER);
    4016 +
    4017 +        pack();
    4018 +    }// </editor-fold>//GEN-END:initComponents
    4019 +
    4020 +    private void bn_time0ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_time0ActionPerformed
    4021 +    {//GEN-HEADEREND:event_bn_time0ActionPerformed
    4022 +        thread.setCurTime(0);
    4023 +    }//GEN-LAST:event_bn_time0ActionPerformed
    4024 +
    4025 +    private void bn_playFwdActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_playFwdActionPerformed
    4026 +    {//GEN-HEADEREND:event_bn_playFwdActionPerformed
    4027 +        thread.setPlayState(PlayerThread.PS_PLAY_FWD);
    4028 +    }//GEN-LAST:event_bn_playFwdActionPerformed
    4029 +
    4030 +    private void bn_stopActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_stopActionPerformed
    4031 +    {//GEN-HEADEREND:event_bn_stopActionPerformed
    4032 +        thread.setPlayState(PlayerThread.PS_STOP);
    4033 +    }//GEN-LAST:event_bn_stopActionPerformed
    4034 +
    4035 +    private void bn_playBackActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_playBackActionPerformed
    4036 +    {//GEN-HEADEREND:event_bn_playBackActionPerformed
    4037 +        thread.setPlayState(PlayerThread.PS_PLAY_BACK);
    4038 +    }//GEN-LAST:event_bn_playBackActionPerformed
    4039 +
    4040 +    private void formWindowClosed(java.awt.event.WindowEvent evt)//GEN-FIRST:event_formWindowClosed
    4041 +    {//GEN-HEADEREND:event_formWindowClosed
    4042 +//        thread.exit();
    4043 +    }//GEN-LAST:event_formWindowClosed
    4044 +
    4045 +    private void text_timeStepFocusLost(java.awt.event.FocusEvent evt)//GEN-FIRST:event_text_timeStepFocusLost
    4046 +    {//GEN-HEADEREND:event_text_timeStepFocusLost
    4047 +        text_timeStepActionPerformed(null);
    4048 +    }//GEN-LAST:event_text_timeStepFocusLost
    4049 +
    4050 +    private void text_timeStepActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_text_timeStepActionPerformed
    4051 +    {//GEN-HEADEREND:event_text_timeStepActionPerformed
    4052 +        try
    4053 +        {
    4054 +            int val = Integer.parseInt(text_timeStep.getText());
    4055 +            thread.setTimeStep(1.0 / val);
    4056 +        }
    4057 +        catch (Exception e)
    4058 +        {
    4059 +        }
    4060 +       
    4061 +        double d = thread.getTimeStep();
    4062 +        String newStrn = "" + (int)(1f / d);
    4063 +        if (newStrn.equals(text_timeStep.getText())) return;
    4064 +        text_timeStep.setText(newStrn);
    4065 +       
    4066 +//        text_timeStepActionPerformed(null);
    4067 +    }//GEN-LAST:event_text_timeStepActionPerformed
    4068 +
    4069 +    private void text_curTimeActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_text_curTimeActionPerformed
    4070 +    {//GEN-HEADEREND:event_text_curTimeActionPerformed
    4071 +        try
    4072 +        {
    4073 +            double val = Double.parseDouble(text_curTime.getText());
    4074 +            thread.setCurTime(val);
    4075 +        }
    4076 +        catch (Exception e)
    4077 +        {
    4078 +        }
    4079 +       
    4080 +        double d = thread.getCurTime();
    4081 +        text_curTime.setText("" + (float)d);
    4082 +       
    4083 +        text_timeStepActionPerformed(null);
    4084 +    }//GEN-LAST:event_text_curTimeActionPerformed
    4085 +
    4086 +    private void text_curTimeFocusLost(java.awt.event.FocusEvent evt)//GEN-FIRST:event_text_curTimeFocusLost
    4087 +    {//GEN-HEADEREND:event_text_curTimeFocusLost
    4088 +        text_curTimeActionPerformed(null);
    4089 +    }//GEN-LAST:event_text_curTimeFocusLost
    4090 +   
    4091 +    // Variables declaration - do not modify//GEN-BEGIN:variables
    4092 +    private javax.swing.JButton bn_playBack;
    4093 +    private javax.swing.JButton bn_playFwd;
    4094 +    private javax.swing.JButton bn_stop;
    4095 +    private javax.swing.JButton bn_time0;
    4096 +    private javax.swing.JLabel jLabel1;
    4097 +    private javax.swing.JLabel jLabel2;
    4098 +    private javax.swing.JPanel jPanel1;
    4099 +    private javax.swing.JPanel jPanel2;
    4100 +    private javax.swing.JPanel jPanel3;
    4101 +    private javax.swing.JPanel jPanel4;
    4102 +    private javax.swing.JTextField text_curTime;
    4103 +    private javax.swing.JTextField text_timeStep;
    4104 +    // End of variables declaration//GEN-END:variables
    4105 +   
    4106 +}
    4107 Index: core/src/com/kitfox/svg/app/PlayerThread.java
    4108 ===================================================================
    4109 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    4110 +++ core/src/com/kitfox/svg/app/PlayerThread.java       2012-06-17 23:56:57.748545052 +0200
    4111 @@ -0,0 +1,129 @@
    4112 +/*
    4113 + * PlayerThread.java
    4114 + *
    4115 + *
    4116 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    4117 + *  Copyright (C) 2004 Mark McKay
    4118 + *
    4119 + *  This library is free software; you can redistribute it and/or
    4120 + *  modify it under the terms of the GNU Lesser General Public
    4121 + *  License as published by the Free Software Foundation; either
    4122 + *  version 2.1 of the License, or (at your option) any later version.
    4123 + *
    4124 + *  This library is distributed in the hope that it will be useful,
    4125 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    4126 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    4127 + *  Lesser General Public License for more details.
    4128 + *
    4129 + *  You should have received a copy of the GNU Lesser General Public
    4130 + *  License along with this library; if not, write to the Free Software
    4131 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    4132 + *
    4133 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    4134 + *  projects can be found at http://www.kitfox.com
    4135 + *
    4136 + * Created on September 28, 2004, 10:07 PM
    4137 + */
    4138 +
    4139 +
    4140 +package com.kitfox.svg.app;
    4141 +
    4142 +import java.util.*;
    4143 +
    4144 +/**
    4145 + *
    4146 + * @author  kitfox
    4147 + */
    4148 +public class PlayerThread implements Runnable
    4149 +{
    4150 +    HashSet listeners = new HashSet();
    4151 +   
    4152 +    double curTime = 0;
    4153 +    double timeStep = .2;
    4154 +   
    4155 +    public static final int PS_STOP = 0;
    4156 +    public static final int PS_PLAY_FWD = 1;
    4157 +    public static final int PS_PLAY_BACK = 2;
    4158 +   
    4159 +    int playState = PS_STOP;
    4160 +   
    4161 +    Thread thread;
    4162 +   
    4163 +    /** Creates a new instance of PlayerThread */
    4164 +    public PlayerThread()
    4165 +    {
    4166 +        thread = new Thread(this);
    4167 +        thread.start();
    4168 +    }
    4169 +   
    4170 +    public void run()
    4171 +    {
    4172 +        while (thread != null)
    4173 +        {
    4174 +            synchronized (this)
    4175 +            {
    4176 +                switch (playState)
    4177 +                {
    4178 +                    case PS_PLAY_FWD:
    4179 +                        curTime += timeStep;
    4180 +                        break;
    4181 +                    case PS_PLAY_BACK:
    4182 +                        curTime -= timeStep;
    4183 +                        if (curTime < 0) curTime = 0;
    4184 +                        break;
    4185 +                    default:
    4186 +                    case PS_STOP:
    4187 +                        break;
    4188 +                }
    4189 +               
    4190 +                fireTimeUpdateEvent();
    4191 +            }
    4192 +           
    4193 +            try
    4194 +            {
    4195 +                Thread.sleep((long)(timeStep * 1000));
    4196 +            }
    4197 +            catch (Exception e)
    4198 +            {
    4199 +                throw new RuntimeException(e);
    4200 +            }
    4201 +        }
    4202 +    }
    4203 +   
    4204 +    public void exit() { thread = null; }
    4205 +    public synchronized void addListener(PlayerThreadListener listener)
    4206 +    {
    4207 +        listeners.add(listener);
    4208 +    }
    4209 +   
    4210 +    public synchronized double getCurTime() { return curTime; }
    4211 +   
    4212 +    public synchronized void setCurTime(double time)
    4213 +    {
    4214 +        curTime = time;
    4215 +    }
    4216 +   
    4217 +    public synchronized double getTimeStep() { return timeStep; }
    4218 +   
    4219 +    public synchronized void setTimeStep(double time)
    4220 +    {
    4221 +        timeStep = time;
    4222 +        if (timeStep < .01) timeStep = .01;
    4223 +    }
    4224 +   
    4225 +    public synchronized int getPlayState() { return playState; }
    4226 +   
    4227 +    public synchronized void setPlayState(int playState)
    4228 +    {
    4229 +        this.playState = playState;
    4230 +    }
    4231 +   
    4232 +    private void fireTimeUpdateEvent()
    4233 +    {
    4234 +        for (Iterator it = listeners.iterator(); it.hasNext();)
    4235 +        {
    4236 +            PlayerThreadListener listener = (PlayerThreadListener)it.next();
    4237 +            listener.updateTime(curTime, timeStep, playState);
    4238 +        }
    4239 +    }
    4240 +}
    4241 Index: core/src/com/kitfox/svg/app/PlayerThreadListener.java
    4242 ===================================================================
    4243 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    4244 +++ core/src/com/kitfox/svg/app/PlayerThreadListener.java       2012-06-17 23:56:57.748545052 +0200
    4245 @@ -0,0 +1,37 @@
    4246 +/*
    4247 + * PlayerThreadListener.java
    4248 + *
    4249 + *
    4250 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    4251 + *  Copyright (C) 2004 Mark McKay
    4252 + *
    4253 + *  This library is free software; you can redistribute it and/or
    4254 + *  modify it under the terms of the GNU Lesser General Public
    4255 + *  License as published by the Free Software Foundation; either
    4256 + *  version 2.1 of the License, or (at your option) any later version.
    4257 + *
    4258 + *  This library is distributed in the hope that it will be useful,
    4259 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    4260 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    4261 + *  Lesser General Public License for more details.
    4262 + *
    4263 + *  You should have received a copy of the GNU Lesser General Public
    4264 + *  License along with this library; if not, write to the Free Software
    4265 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    4266 + *
    4267 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    4268 + *  projects can be found at http://www.kitfox.com
    4269 + *
    4270 + * Created on September 28, 2004, 10:15 PM
    4271 + */
    4272 +
    4273 +package com.kitfox.svg.app;
    4274 +
    4275 +/**
    4276 + *
    4277 + * @author  kitfox
    4278 + */
    4279 +public interface PlayerThreadListener
    4280 +{
    4281 +    public void updateTime(double curTime, double timeStep, int playState);
    4282 +}
    4283 Index: core/src/com/kitfox/svg/app/SVGPlayer.java
    4284 ===================================================================
    4285 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    4286 +++ core/src/com/kitfox/svg/app/SVGPlayer.java  2012-06-17 23:56:57.748545052 +0200
    4287 @@ -0,0 +1,436 @@
    4288 +/*
    4289 + * SVGViewer.java
    4290 + *
    4291 + *
    4292 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    4293 + *  Copyright (C) 2004 Mark McKay
    4294 + *
    4295 + *  This library is free software; you can redistribute it and/or
    4296 + *  modify it under the terms of the GNU Lesser General Public
    4297 + *  License as published by the Free Software Foundation; either
    4298 + *  version 2.1 of the License, or (at your option) any later version.
    4299 + *
    4300 + *  This library is distributed in the hope that it will be useful,
    4301 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    4302 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    4303 + *  Lesser General Public License for more details.
    4304 + *
    4305 + *  You should have received a copy of the GNU Lesser General Public
    4306 + *  License along with this library; if not, write to the Free Software
    4307 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    4308 + *
    4309 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    4310 + *  projects can be found at http://www.kitfox.com
    4311 + *
    4312 + * Created on April 3, 2004, 5:28 PM
    4313 + */
    4314 +
    4315 +package com.kitfox.svg.app;
    4316 +
    4317 +
    4318 +import com.kitfox.svg.SVGDiagram;
    4319 +import com.kitfox.svg.SVGDisplayPanel;
    4320 +import com.kitfox.svg.SVGElement;
    4321 +import com.kitfox.svg.SVGException;
    4322 +import com.kitfox.svg.SVGUniverse;
    4323 +import java.awt.Color;
    4324 +import java.awt.event.MouseAdapter;
    4325 +import java.awt.event.MouseEvent;
    4326 +import java.awt.geom.Point2D;
    4327 +import java.io.File;
    4328 +import java.io.InputStream;
    4329 +import java.net.URI;
    4330 +import java.net.URL;
    4331 +import java.net.URLEncoder;
    4332 +import java.security.AccessControlException;
    4333 +import java.util.ArrayList;
    4334 +import java.util.List;
    4335 +import java.util.Vector;
    4336 +import java.util.regex.Matcher;
    4337 +import java.util.regex.Pattern;
    4338 +import javax.swing.JFileChooser;
    4339 +import javax.swing.JOptionPane;
    4340 +
    4341 +/**
    4342 + * @author Mark McKay
    4343 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    4344 + */
    4345 +public class SVGPlayer extends javax.swing.JFrame
    4346 +{
    4347 +    public static final long serialVersionUID = 1;
    4348 +
    4349 +    SVGDisplayPanel svgDisplayPanel = new SVGDisplayPanel();
    4350 +
    4351 +    final PlayerDialog playerDialog;
    4352 +   
    4353 +    SVGUniverse universe;
    4354 +   
    4355 +    /** FileChooser for running in trusted environments */
    4356 +    final JFileChooser fileChooser;
    4357 +    {
    4358 +//        fileChooser = new JFileChooser(new File("."));
    4359 +        JFileChooser fc = null;
    4360 +        try
    4361 +        {
    4362 +            fc = new JFileChooser();
    4363 +            fc.setFileFilter(
    4364 +                new javax.swing.filechooser.FileFilter() {
    4365 +                    final Matcher matchLevelFile = Pattern.compile(".*\\.svg[z]?").matcher("");
    4366 +
    4367 +                    public boolean accept(File file)
    4368 +                    {
    4369 +                        if (file.isDirectory()) return true;
    4370 +
    4371 +                        matchLevelFile.reset(file.getName());
    4372 +                        return matchLevelFile.matches();
    4373 +                    }
    4374 +
    4375 +                    public String getDescription() { return "SVG file (*.svg, *.svgz)"; }
    4376 +                }
    4377 +            );
    4378 +        }
    4379 +        catch (AccessControlException ex)
    4380 +        {
    4381 +            //Do not create file chooser if webstart refuses permissions
    4382 +        }
    4383 +        fileChooser = fc;
    4384 +    }
    4385 +
    4386 +    /** Backup file service for opening files in WebStart situations */
    4387 +    /*
    4388 +    final FileOpenService fileOpenService;
    4389 +    {
    4390 +        try
    4391 +        {
    4392 +            fileOpenService = (FileOpenService)ServiceManager.lookup("javax.jnlp.FileOpenService");
    4393 +        }
    4394 +        catch (UnavailableServiceException e)
    4395 +        {
    4396 +            fileOpenService = null;
    4397 +        }
    4398 +    }
    4399 +     */
    4400 +   
    4401 +    /** Creates new form SVGViewer */
    4402 +    public SVGPlayer() {
    4403 +        initComponents();
    4404 +
    4405 +        setSize(800, 600);
    4406 +
    4407 +        svgDisplayPanel.setBgColor(Color.white);
    4408 +        svgDisplayPanel.addMouseListener(new MouseAdapter()
    4409 +        {
    4410 +            public void mouseClicked(MouseEvent evt)
    4411 +            {
    4412 +                SVGDiagram diagram = svgDisplayPanel.getDiagram();
    4413 +                if (diagram == null) return;
    4414 +               
    4415 +                System.out.println("Picking at cursor (" + evt.getX() + ", " + evt.getY() + ")");
    4416 +                try
    4417 +                {
    4418 +                    List paths = diagram.pick(new Point2D.Float(evt.getX(), evt.getY()), null);
    4419 +                    for (int i = 0; i < paths.size(); i++)
    4420 +                    {
    4421 +                        ArrayList path = (ArrayList)paths.get(i);
    4422 +                        System.out.println(pathToString(path));
    4423 +                    }
    4424 +                }
    4425 +                catch (SVGException ex)
    4426 +                {
    4427 +                    ex.printStackTrace();
    4428 +                }
    4429 +            }
    4430 +        }
    4431 +        );
    4432 +       
    4433 +        svgDisplayPanel.setPreferredSize(getSize());
    4434 +        scrollPane_svgArea.setViewportView(svgDisplayPanel);
    4435 +       
    4436 +        playerDialog = new PlayerDialog(this);
    4437 +    }
    4438 +   
    4439 +    private String pathToString(List path)
    4440 +    {
    4441 +        if (path.size() == 0) return "";
    4442 +       
    4443 +        StringBuffer sb = new StringBuffer();
    4444 +        sb.append(path.get(0));
    4445 +        for (int i = 1; i < path.size(); i++)
    4446 +        {
    4447 +            sb.append("/");
    4448 +            sb.append(((SVGElement)path.get(i)).getId());
    4449 +        }
    4450 +        return sb.toString();
    4451 +    }
    4452 +   
    4453 +    public void updateTime(double curTime)
    4454 +    {
    4455 +        try
    4456 +        {
    4457 +            if (universe != null)
    4458 +            {
    4459 +                universe.setCurTime(curTime);
    4460 +                universe.updateTime();
    4461 +    //            svgDisplayPanel.updateTime(curTime);
    4462 +                repaint();
    4463 +            }
    4464 +        }
    4465 +        catch (Exception e)
    4466 +        {
    4467 +            e.printStackTrace();
    4468 +        }
    4469 +    }
    4470 +
    4471 +    private void loadURL(URL url)
    4472 +    {
    4473 +        boolean verbose = cmCheck_verbose.isSelected();
    4474 +
    4475 +        universe = new SVGUniverse();
    4476 +        universe.setVerbose(verbose);
    4477 +        SVGDiagram diagram = null;
    4478 +
    4479 +        if (!CheckBoxMenuItem_anonInputStream.isSelected())
    4480 +        {
    4481 +            //Load from a disk with a valid URL
    4482 +            URI uri = universe.loadSVG(url);
    4483 +
    4484 +            if (verbose) System.err.println(uri.toString());
    4485 +
    4486 +            diagram = universe.getDiagram(uri);
    4487 +        }
    4488 +        else
    4489 +        {
    4490 +            //Load from a stream with no particular valid URL
    4491 +            try
    4492 +            {
    4493 +                InputStream is = url.openStream();
    4494 +                URI uri = universe.loadSVG(is, "defaultName");
    4495 +
    4496 +                if (verbose) System.err.println(uri.toString());
    4497 +
    4498 +                diagram = universe.getDiagram(uri);
    4499 +            }
    4500 +            catch (Exception e)
    4501 +            {
    4502 +                e.printStackTrace();
    4503 +            }
    4504 +        }
    4505 +
    4506 +        svgDisplayPanel.setDiagram(diagram);
    4507 +        repaint();
    4508 +    }
    4509 +   
    4510 +    /** This method is called from within the constructor to
    4511 +     * initialize the form.
    4512 +     * WARNING: Do NOT modify this code. The content of this method is
    4513 +     * always regenerated by the Form Editor.
    4514 +     */
    4515 +    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    4516 +    private void initComponents()
    4517 +    {
    4518 +        scrollPane_svgArea = new javax.swing.JScrollPane();
    4519 +        jMenuBar1 = new javax.swing.JMenuBar();
    4520 +        menu_file = new javax.swing.JMenu();
    4521 +        cm_loadFile = new javax.swing.JMenuItem();
    4522 +        cm_loadUrl = new javax.swing.JMenuItem();
    4523 +        menu_window = new javax.swing.JMenu();
    4524 +        cm_player = new javax.swing.JMenuItem();
    4525 +        jSeparator2 = new javax.swing.JSeparator();
    4526 +        cm_800x600 = new javax.swing.JMenuItem();
    4527 +        CheckBoxMenuItem_anonInputStream = new javax.swing.JCheckBoxMenuItem();
    4528 +        cmCheck_verbose = new javax.swing.JCheckBoxMenuItem();
    4529 +        menu_help = new javax.swing.JMenu();
    4530 +        cm_about = new javax.swing.JMenuItem();
    4531 +
    4532 +        setTitle("SVG Player - Salamander Project");
    4533 +        addWindowListener(new java.awt.event.WindowAdapter()
    4534 +        {
    4535 +            public void windowClosing(java.awt.event.WindowEvent evt)
    4536 +            {
    4537 +                exitForm(evt);
    4538 +            }
    4539 +        });
    4540 +
    4541 +        getContentPane().add(scrollPane_svgArea, java.awt.BorderLayout.CENTER);
    4542 +
    4543 +        menu_file.setMnemonic('f');
    4544 +        menu_file.setText("File");
    4545 +        cm_loadFile.setMnemonic('l');
    4546 +        cm_loadFile.setText("Load File...");
    4547 +        cm_loadFile.addActionListener(new java.awt.event.ActionListener()
    4548 +        {
    4549 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    4550 +            {
    4551 +                cm_loadFileActionPerformed(evt);
    4552 +            }
    4553 +        });
    4554 +
    4555 +        menu_file.add(cm_loadFile);
    4556 +
    4557 +        cm_loadUrl.setText("Load URL...");
    4558 +        cm_loadUrl.addActionListener(new java.awt.event.ActionListener()
    4559 +        {
    4560 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    4561 +            {
    4562 +                cm_loadUrlActionPerformed(evt);
    4563 +            }
    4564 +        });
    4565 +
    4566 +        menu_file.add(cm_loadUrl);
    4567 +
    4568 +        jMenuBar1.add(menu_file);
    4569 +
    4570 +        menu_window.setText("Window");
    4571 +        cm_player.setText("Player");
    4572 +        cm_player.addActionListener(new java.awt.event.ActionListener()
    4573 +        {
    4574 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    4575 +            {
    4576 +                cm_playerActionPerformed(evt);
    4577 +            }
    4578 +        });
    4579 +
    4580 +        menu_window.add(cm_player);
    4581 +
    4582 +        menu_window.add(jSeparator2);
    4583 +
    4584 +        cm_800x600.setText("800 x 600");
    4585 +        cm_800x600.addActionListener(new java.awt.event.ActionListener()
    4586 +        {
    4587 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    4588 +            {
    4589 +                cm_800x600ActionPerformed(evt);
    4590 +            }
    4591 +        });
    4592 +
    4593 +        menu_window.add(cm_800x600);
    4594 +
    4595 +        CheckBoxMenuItem_anonInputStream.setText("Anonymous Input Stream");
    4596 +        menu_window.add(CheckBoxMenuItem_anonInputStream);
    4597 +
    4598 +        cmCheck_verbose.setText("Verbose");
    4599 +        cmCheck_verbose.addActionListener(new java.awt.event.ActionListener()
    4600 +        {
    4601 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    4602 +            {
    4603 +                cmCheck_verboseActionPerformed(evt);
    4604 +            }
    4605 +        });
    4606 +
    4607 +        menu_window.add(cmCheck_verbose);
    4608 +
    4609 +        jMenuBar1.add(menu_window);
    4610 +
    4611 +        menu_help.setText("Help");
    4612 +        cm_about.setText("About...");
    4613 +        cm_about.addActionListener(new java.awt.event.ActionListener()
    4614 +        {
    4615 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    4616 +            {
    4617 +                cm_aboutActionPerformed(evt);
    4618 +            }
    4619 +        });
    4620 +
    4621 +        menu_help.add(cm_about);
    4622 +
    4623 +        jMenuBar1.add(menu_help);
    4624 +
    4625 +        setJMenuBar(jMenuBar1);
    4626 +
    4627 +        pack();
    4628 +    }// </editor-fold>//GEN-END:initComponents
    4629 +
    4630 +    private void cm_loadUrlActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadUrlActionPerformed
    4631 +    {//GEN-HEADEREND:event_cm_loadUrlActionPerformed
    4632 +        String urlStrn = JOptionPane.showInputDialog(this, "Enter URL of SVG file");
    4633 +        if (urlStrn == null) return;
    4634 +       
    4635 +        try
    4636 +        {
    4637 +            URL url = new URL(URLEncoder.encode(urlStrn, "UTF-8"));
    4638 +            loadURL(url);
    4639 +        }
    4640 +        catch (Exception e)
    4641 +        {
    4642 +            e.printStackTrace();
    4643 +        }
    4644 +
    4645 +    }//GEN-LAST:event_cm_loadUrlActionPerformed
    4646 +
    4647 +    private void cmCheck_verboseActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cmCheck_verboseActionPerformed
    4648 +    {//GEN-HEADEREND:event_cmCheck_verboseActionPerformed
    4649 +// TODO add your handling code here:
    4650 +    }//GEN-LAST:event_cmCheck_verboseActionPerformed
    4651 +
    4652 +    private void cm_playerActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_playerActionPerformed
    4653 +    {//GEN-HEADEREND:event_cm_playerActionPerformed
    4654 +        playerDialog.setVisible(true);
    4655 +    }//GEN-LAST:event_cm_playerActionPerformed
    4656 +
    4657 +    private void cm_aboutActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_aboutActionPerformed
    4658 +    {//GEN-HEADEREND:event_cm_aboutActionPerformed
    4659 +        VersionDialog dia = new VersionDialog(this, true, cmCheck_verbose.isSelected());
    4660 +        dia.setVisible(true);
    4661 +//        JOptionPane.showMessageDialog(this, "Salamander SVG - Created by Mark McKay\nhttp://www.kitfox.com");
    4662 +    }//GEN-LAST:event_cm_aboutActionPerformed
    4663 +
    4664 +    private void cm_800x600ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cm_800x600ActionPerformed
    4665 +        setSize(800, 600);
    4666 +    }//GEN-LAST:event_cm_800x600ActionPerformed
    4667 +   
    4668 +    private void cm_loadFileActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadFileActionPerformed
    4669 +    {//GEN-HEADEREND:event_cm_loadFileActionPerformed
    4670 +        boolean verbose = cmCheck_verbose.isSelected();
    4671 +       
    4672 +        try
    4673 +        {
    4674 +            int retVal = fileChooser.showOpenDialog(this);
    4675 +            if (retVal == JFileChooser.APPROVE_OPTION)
    4676 +            {
    4677 +                File chosenFile = fileChooser.getSelectedFile();
    4678 +
    4679 +                URL url = chosenFile.toURI().toURL();
    4680 +
    4681 +                loadURL(url);
    4682 +            }
    4683 +        }
    4684 +        catch (Exception e)
    4685 +        {
    4686 +            e.printStackTrace();
    4687 +        }
    4688 +
    4689 +    }//GEN-LAST:event_cm_loadFileActionPerformed
    4690 +
    4691 +    /** Exit the Application */
    4692 +    private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
    4693 +        System.exit(0);
    4694 +    }//GEN-LAST:event_exitForm
    4695 +
    4696 +    /**
    4697 +     * @param args the command line arguments
    4698 +     */
    4699 +    public static void main(String args[]) {
    4700 +        new SVGPlayer().setVisible(true);
    4701 +    }
    4702 +
    4703 +    public void updateTime(double curTime, double timeStep, int playState)
    4704 +    {
    4705 +    }
    4706 +   
    4707 +    // Variables declaration - do not modify//GEN-BEGIN:variables
    4708 +    private javax.swing.JCheckBoxMenuItem CheckBoxMenuItem_anonInputStream;
    4709 +    private javax.swing.JCheckBoxMenuItem cmCheck_verbose;
    4710 +    private javax.swing.JMenuItem cm_800x600;
    4711 +    private javax.swing.JMenuItem cm_about;
    4712 +    private javax.swing.JMenuItem cm_loadFile;
    4713 +    private javax.swing.JMenuItem cm_loadUrl;
    4714 +    private javax.swing.JMenuItem cm_player;
    4715 +    private javax.swing.JMenuBar jMenuBar1;
    4716 +    private javax.swing.JSeparator jSeparator2;
    4717 +    private javax.swing.JMenu menu_file;
    4718 +    private javax.swing.JMenu menu_help;
    4719 +    private javax.swing.JMenu menu_window;
    4720 +    private javax.swing.JScrollPane scrollPane_svgArea;
    4721 +    // End of variables declaration//GEN-END:variables
    4722 +
    4723 +}
    4724 Index: core/src/com/kitfox/svg/app/SVGViewer.java
    4725 ===================================================================
    4726 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    4727 +++ core/src/com/kitfox/svg/app/SVGViewer.java  2012-06-17 23:56:57.752545052 +0200
    4728 @@ -0,0 +1,432 @@
    4729 +/*
    4730 + * SVGViewer.java
    4731 + *
    4732 + *
    4733 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    4734 + *  Copyright (C) 2004 Mark McKay
    4735 + *
    4736 + *  This library is free software; you can redistribute it and/or
    4737 + *  modify it under the terms of the GNU Lesser General Public
    4738 + *  License as published by the Free Software Foundation; either
    4739 + *  version 2.1 of the License, or (at your option) any later version.
    4740 + *
    4741 + *  This library is distributed in the hope that it will be useful,
    4742 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    4743 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    4744 + *  Lesser General Public License for more details.
    4745 + *
    4746 + *  You should have received a copy of the GNU Lesser General Public
    4747 + *  License along with this library; if not, write to the Free Software
    4748 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    4749 + *
    4750 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    4751 + *  projects can be found at http://www.kitfox.com
    4752 + *
    4753 + * Created on April 3, 2004, 5:28 PM
    4754 + */
    4755 +
    4756 +package com.kitfox.svg.app;
    4757 +
    4758 +import com.kitfox.svg.SVGCache;
    4759 +import com.kitfox.svg.SVGDiagram;
    4760 +import com.kitfox.svg.SVGDisplayPanel;
    4761 +import com.kitfox.svg.SVGElement;
    4762 +import com.kitfox.svg.SVGException;
    4763 +import com.kitfox.svg.SVGUniverse;
    4764 +import java.awt.BorderLayout;
    4765 +import java.awt.Color;
    4766 +import java.awt.Point;
    4767 +import java.io.File;
    4768 +import java.io.InputStream;
    4769 +import java.net.URI;
    4770 +import java.net.URL;
    4771 +import java.net.URLEncoder;
    4772 +import java.security.AccessControlException;
    4773 +import java.util.ArrayList;
    4774 +import java.util.Iterator;
    4775 +import java.util.List;
    4776 +import java.util.regex.Matcher;
    4777 +import java.util.regex.Pattern;
    4778 +import javax.swing.JFileChooser;
    4779 +import javax.swing.JOptionPane;
    4780 +
    4781 +
    4782 +/**
    4783 + * @author Mark McKay
    4784 + * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
    4785 + */
    4786 +public class SVGViewer extends javax.swing.JFrame
    4787 +{
    4788 +    public static final long serialVersionUID = 1;
    4789 +
    4790 +    SVGDisplayPanel svgDisplayPanel = new SVGDisplayPanel();
    4791 +
    4792 +    /** FileChooser for running in trusted environments */
    4793 +    final JFileChooser fileChooser;
    4794 +    {
    4795 +//        fileChooser = new JFileChooser(new File("."));
    4796 +        JFileChooser fc = null;
    4797 +        try
    4798 +        {
    4799 +            fc = new JFileChooser();
    4800 +            fc.setFileFilter(
    4801 +                new javax.swing.filechooser.FileFilter() {
    4802 +                    final Matcher matchLevelFile = Pattern.compile(".*\\.svg[z]?").matcher("");
    4803 +
    4804 +                    public boolean accept(File file)
    4805 +                    {
    4806 +                        if (file.isDirectory()) return true;
    4807 +
    4808 +                        matchLevelFile.reset(file.getName());
    4809 +                        return matchLevelFile.matches();
    4810 +                    }
    4811 +
    4812 +                    public String getDescription() { return "SVG file (*.svg, *.svgz)"; }
    4813 +                }
    4814 +            );
    4815 +        }
    4816 +        catch (AccessControlException ex)
    4817 +        {
    4818 +            //Do not create file chooser if webstart refuses permissions
    4819 +        }
    4820 +        fileChooser = fc;
    4821 +    }
    4822 +
    4823 +    /** Backup file service for opening files in WebStart situations */
    4824 +    /*
    4825 +    final FileOpenService fileOpenService;
    4826 +    {
    4827 +        try
    4828 +        {
    4829 +            fileOpenService = (FileOpenService)ServiceManager.lookup("javax.jnlp.FileOpenService");
    4830 +        }
    4831 +        catch (UnavailableServiceException e)
    4832 +        {
    4833 +            fileOpenService = null;
    4834 +        }
    4835 +    }
    4836 +     */
    4837 +   
    4838 +    /** Creates new form SVGViewer */
    4839 +    public SVGViewer() {
    4840 +        initComponents();
    4841 +
    4842 +        setSize(800, 600);
    4843 +
    4844 +        svgDisplayPanel.setBgColor(Color.white);
    4845 +
    4846 +        svgDisplayPanel.setPreferredSize(getSize());
    4847 +        panel_svgArea.add(svgDisplayPanel, BorderLayout.CENTER);
    4848 +//        scrollPane_svgArea.setViewportView(svgDisplayPanel);
    4849 +    }
    4850 +
    4851 +    private void loadURL(URL url)
    4852 +    {
    4853 +        boolean verbose = cmCheck_verbose.isSelected();
    4854 +       
    4855 +//                SVGUniverse universe = new SVGUniverse();
    4856 +        SVGUniverse universe = SVGCache.getSVGUniverse();
    4857 +        SVGDiagram diagram = null;
    4858 +        URI uri;
    4859 +
    4860 +        if (!CheckBoxMenuItem_anonInputStream.isSelected())
    4861 +        {
    4862 +            //Load from a disk with a valid URL
    4863 +            uri = universe.loadSVG(url);
    4864 +
    4865 +            if (verbose) System.err.println("Loading document " + uri.toString());
    4866 +
    4867 +            diagram = universe.getDiagram(uri);
    4868 +        }
    4869 +        else
    4870 +        {
    4871 +            //Load from a stream with no particular valid URL
    4872 +            try
    4873 +            {
    4874 +                InputStream is = url.openStream();
    4875 +                uri = universe.loadSVG(is, "defaultName");
    4876 +
    4877 +                if (verbose) System.err.println("Loading document " + uri.toString());
    4878 +            }
    4879 +            catch (Exception e)
    4880 +            {
    4881 +                e.printStackTrace();
    4882 +                return;
    4883 +            }
    4884 +        }
    4885 +/*
    4886 +ByteArrayOutputStream bs = new ByteArrayOutputStream();
    4887 +ObjectOutputStream os = new ObjectOutputStream(bs);
    4888 +os.writeObject(universe);
    4889 +os.close();
    4890 +
    4891 +ByteArrayInputStream bin = new ByteArrayInputStream(bs.toByteArray());
    4892 +ObjectInputStream is = new ObjectInputStream(bin);
    4893 +universe = (SVGUniverse)is.readObject();
    4894 +is.close();
    4895 +*/
    4896 +
    4897 +        diagram = universe.getDiagram(uri);
    4898 +
    4899 +        svgDisplayPanel.setDiagram(diagram);
    4900 +        repaint();
    4901 +    }
    4902 +   
    4903 +    /** This method is called from within the constructor to
    4904 +     * initialize the form.
    4905 +     * WARNING: Do NOT modify this code. The content of this method is
    4906 +     * always regenerated by the Form Editor.
    4907 +     */
    4908 +    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    4909 +    private void initComponents()
    4910 +    {
    4911 +        scrollPane_svgArea = new javax.swing.JScrollPane();
    4912 +        panel_svgArea = new javax.swing.JPanel();
    4913 +        jMenuBar1 = new javax.swing.JMenuBar();
    4914 +        menu_file = new javax.swing.JMenu();
    4915 +        cm_loadFile = new javax.swing.JMenuItem();
    4916 +        cm_loadUrl = new javax.swing.JMenuItem();
    4917 +        menu_window = new javax.swing.JMenu();
    4918 +        cm_800x600 = new javax.swing.JMenuItem();
    4919 +        CheckBoxMenuItem_anonInputStream = new javax.swing.JCheckBoxMenuItem();
    4920 +        cmCheck_verbose = new javax.swing.JCheckBoxMenuItem();
    4921 +        menu_help = new javax.swing.JMenu();
    4922 +        cm_about = new javax.swing.JMenuItem();
    4923 +
    4924 +        setTitle("SVG Viewer - Salamander Project");
    4925 +        addWindowListener(new java.awt.event.WindowAdapter()
    4926 +        {
    4927 +            public void windowClosing(java.awt.event.WindowEvent evt)
    4928 +            {
    4929 +                exitForm(evt);
    4930 +            }
    4931 +        });
    4932 +
    4933 +        panel_svgArea.setLayout(new java.awt.BorderLayout());
    4934 +
    4935 +        panel_svgArea.addMouseListener(new java.awt.event.MouseAdapter()
    4936 +        {
    4937 +            public void mousePressed(java.awt.event.MouseEvent evt)
    4938 +            {
    4939 +                panel_svgAreaMousePressed(evt);
    4940 +            }
    4941 +            public void mouseReleased(java.awt.event.MouseEvent evt)
    4942 +            {
    4943 +                panel_svgAreaMouseReleased(evt);
    4944 +            }
    4945 +        });
    4946 +
    4947 +        scrollPane_svgArea.setViewportView(panel_svgArea);
    4948 +
    4949 +        getContentPane().add(scrollPane_svgArea, java.awt.BorderLayout.CENTER);
    4950 +
    4951 +        menu_file.setMnemonic('f');
    4952 +        menu_file.setText("File");
    4953 +        cm_loadFile.setMnemonic('l');
    4954 +        cm_loadFile.setText("Load File...");
    4955 +        cm_loadFile.addActionListener(new java.awt.event.ActionListener()
    4956 +        {
    4957 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    4958 +            {
    4959 +                cm_loadFileActionPerformed(evt);
    4960 +            }
    4961 +        });
    4962 +
    4963 +        menu_file.add(cm_loadFile);
    4964 +
    4965 +        cm_loadUrl.setText("Load URL...");
    4966 +        cm_loadUrl.addActionListener(new java.awt.event.ActionListener()
    4967 +        {
    4968 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    4969 +            {
    4970 +                cm_loadUrlActionPerformed(evt);
    4971 +            }
    4972 +        });
    4973 +
    4974 +        menu_file.add(cm_loadUrl);
    4975 +
    4976 +        jMenuBar1.add(menu_file);
    4977 +
    4978 +        menu_window.setText("Window");
    4979 +        cm_800x600.setText("800 x 600");
    4980 +        cm_800x600.addActionListener(new java.awt.event.ActionListener()
    4981 +        {
    4982 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    4983 +            {
    4984 +                cm_800x600ActionPerformed(evt);
    4985 +            }
    4986 +        });
    4987 +
    4988 +        menu_window.add(cm_800x600);
    4989 +
    4990 +        CheckBoxMenuItem_anonInputStream.setText("Anonymous Input Stream");
    4991 +        menu_window.add(CheckBoxMenuItem_anonInputStream);
    4992 +
    4993 +        cmCheck_verbose.setText("Verbose");
    4994 +        cmCheck_verbose.addActionListener(new java.awt.event.ActionListener()
    4995 +        {
    4996 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    4997 +            {
    4998 +                cmCheck_verboseActionPerformed(evt);
    4999 +            }
    5000 +        });
    5001 +
    5002 +        menu_window.add(cmCheck_verbose);
    5003 +
    5004 +        jMenuBar1.add(menu_window);
    5005 +
    5006 +        menu_help.setText("Help");
    5007 +        cm_about.setText("About...");
    5008 +        cm_about.addActionListener(new java.awt.event.ActionListener()
    5009 +        {
    5010 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    5011 +            {
    5012 +                cm_aboutActionPerformed(evt);
    5013 +            }
    5014 +        });
    5015 +
    5016 +        menu_help.add(cm_about);
    5017 +
    5018 +        jMenuBar1.add(menu_help);
    5019 +
    5020 +        setJMenuBar(jMenuBar1);
    5021 +
    5022 +        pack();
    5023 +    }// </editor-fold>//GEN-END:initComponents
    5024 +
    5025 +    private void cm_loadUrlActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadUrlActionPerformed
    5026 +    {//GEN-HEADEREND:event_cm_loadUrlActionPerformed
    5027 +        String urlStrn = JOptionPane.showInputDialog(this, "Enter URL of SVG file");
    5028 +        if (urlStrn == null) return;
    5029 +       
    5030 +        try
    5031 +        {
    5032 +            URL url = new URL(URLEncoder.encode(urlStrn, "UTF-8"));
    5033 +            loadURL(url);
    5034 +        }
    5035 +        catch (Exception e)
    5036 +        {
    5037 +            e.printStackTrace();
    5038 +        }
    5039 +
    5040 +    }//GEN-LAST:event_cm_loadUrlActionPerformed
    5041 +
    5042 +    private void panel_svgAreaMouseReleased(java.awt.event.MouseEvent evt)//GEN-FIRST:event_panel_svgAreaMouseReleased
    5043 +    {//GEN-HEADEREND:event_panel_svgAreaMouseReleased
    5044 +        SVGDiagram diagram = svgDisplayPanel.getDiagram();
    5045 +        List pickedElements;
    5046 +        try
    5047 +        {
    5048 +            pickedElements = diagram.pick(new Point(evt.getX(), evt.getY()), null);
    5049 +        }
    5050 +        catch (SVGException ex)
    5051 +        {
    5052 +            ex.printStackTrace();
    5053 +            return;
    5054 +        }
    5055 +       
    5056 +        System.out.println("Pick results:");
    5057 +        for (Iterator it = pickedElements.iterator(); it.hasNext();)
    5058 +        {
    5059 +            ArrayList path = (ArrayList)it.next();
    5060 +           
    5061 +            System.out.print("  Path: ");
    5062 +           
    5063 +            for (Iterator it2 = path.iterator(); it2.hasNext();)
    5064 +            {
    5065 +                SVGElement ele = (SVGElement)it2.next();
    5066 +
    5067 +                System.out.print("" + ele.getId() + "(" + ele.getClass().getName() + ") ");
    5068 +            }
    5069 +            System.out.println();
    5070 +        }
    5071 +    }//GEN-LAST:event_panel_svgAreaMouseReleased
    5072 +
    5073 +    private void panel_svgAreaMousePressed(java.awt.event.MouseEvent evt)//GEN-FIRST:event_panel_svgAreaMousePressed
    5074 +    {//GEN-HEADEREND:event_panel_svgAreaMousePressed
    5075 +
    5076 +    }//GEN-LAST:event_panel_svgAreaMousePressed
    5077 +
    5078 +    private void cmCheck_verboseActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cmCheck_verboseActionPerformed
    5079 +    {//GEN-HEADEREND:event_cmCheck_verboseActionPerformed
    5080 +        SVGCache.getSVGUniverse().setVerbose(cmCheck_verbose.isSelected());
    5081 +    }//GEN-LAST:event_cmCheck_verboseActionPerformed
    5082 +
    5083 +    private void cm_aboutActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_aboutActionPerformed
    5084 +    {//GEN-HEADEREND:event_cm_aboutActionPerformed
    5085 +        //JOptionPane.showMessageDialog(this, "Salamander SVG - Created by Mark McKay\nhttp://www.kitfox.com");
    5086 +        VersionDialog dlg = new VersionDialog(this, true, cmCheck_verbose.isSelected());
    5087 +        dlg.setVisible(true);
    5088 +    }//GEN-LAST:event_cm_aboutActionPerformed
    5089 +
    5090 +    private void cm_800x600ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cm_800x600ActionPerformed
    5091 +        setSize(800, 600);
    5092 +    }//GEN-LAST:event_cm_800x600ActionPerformed
    5093 +   
    5094 +    private void cm_loadFileActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadFileActionPerformed
    5095 +    {//GEN-HEADEREND:event_cm_loadFileActionPerformed
    5096 +        try
    5097 +        {
    5098 +            int retVal = fileChooser.showOpenDialog(this);
    5099 +            if (retVal == JFileChooser.APPROVE_OPTION)
    5100 +            {
    5101 +                File chosenFile = fileChooser.getSelectedFile();
    5102 +
    5103 +                URL url = chosenFile.toURI().toURL();
    5104 +
    5105 +                loadURL(url);
    5106 +            }
    5107 +        }
    5108 +        /*
    5109 +        catch (IOException ioe)
    5110 +        {
    5111 +            try
    5112 +            {
    5113 +                //We may be in a WebStart app.  Try again with a FileOpenService
    5114 +                FileContents fc = fileOpenService.openFileDialog(null, new String[]{"svg"});
    5115 +                InputStream is = fc.getInputStream();
    5116 +                String name = fc.getName();
    5117 +            }
    5118 +            catch (Exception e)
    5119 +            {
    5120 +                e.printStackTrace();
    5121 +            }
    5122 +        }
    5123 +         */
    5124 +        catch (Exception e)
    5125 +        {
    5126 +            e.printStackTrace();
    5127 +        }
    5128 +
    5129 +    }//GEN-LAST:event_cm_loadFileActionPerformed
    5130 +
    5131 +    /** Exit the Application */
    5132 +    private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
    5133 +//        setVisible(false);
    5134 +//        dispose();
    5135 +        System.exit(0);
    5136 +    }//GEN-LAST:event_exitForm
    5137 +
    5138 +    /**
    5139 +     * @param args the command line arguments
    5140 +     */
    5141 +    public static void main(String args[]) {
    5142 +        new SVGViewer().setVisible(true);
    5143 +    }
    5144 +
    5145 +    // Variables declaration - do not modify//GEN-BEGIN:variables
    5146 +    private javax.swing.JCheckBoxMenuItem CheckBoxMenuItem_anonInputStream;
    5147 +    private javax.swing.JCheckBoxMenuItem cmCheck_verbose;
    5148 +    private javax.swing.JMenuItem cm_800x600;
    5149 +    private javax.swing.JMenuItem cm_about;
    5150 +    private javax.swing.JMenuItem cm_loadFile;
    5151 +    private javax.swing.JMenuItem cm_loadUrl;
    5152 +    private javax.swing.JMenuBar jMenuBar1;
    5153 +    private javax.swing.JMenu menu_file;
    5154 +    private javax.swing.JMenu menu_help;
    5155 +    private javax.swing.JMenu menu_window;
    5156 +    private javax.swing.JPanel panel_svgArea;
    5157 +    private javax.swing.JScrollPane scrollPane_svgArea;
    5158 +    // End of variables declaration//GEN-END:variables
    5159 +
    5160 +}
    5161 Index: core/src/com/kitfox/svg/app/VersionDialog.java
    5162 ===================================================================
    5163 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    5164 +++ core/src/com/kitfox/svg/app/VersionDialog.java      2012-06-17 23:56:57.752545052 +0200
    5165 @@ -0,0 +1,151 @@
    5166 +/*
    5167 + * VersionDialog.java
    5168 + *
    5169 + *
    5170 + *  The Salamander Project - 2D and 3D graphics libraries in Java
    5171 + *  Copyright (C) 2004 Mark McKay
    5172 + *
    5173 + *  This library is free software; you can redistribute it and/or
    5174 + *  modify it under the terms of the GNU Lesser General Public
    5175 + *  License as published by the Free Software Foundation; either
    5176 + *  version 2.1 of the License, or (at your option) any later version.
    5177 + *
    5178 + *  This library is distributed in the hope that it will be useful,
    5179 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    5180 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    5181 + *  Lesser General Public License for more details.
    5182 + *
    5183 + *  You should have received a copy of the GNU Lesser General Public
    5184 + *  License along with this library; if not, write to the Free Software
    5185 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    5186 + *
    5187 + *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
    5188 + *  projects can be found at http://www.kitfox.com
    5189 + *
    5190 + * Created on January 13, 2005, 7:23 AM
    5191 + */
    5192 +
    5193 +package com.kitfox.svg.app;
    5194 +
    5195 +import java.net.*;
    5196 +import java.io.*;
    5197 +import java.util.*;
    5198 +import javax.swing.event.*;
    5199 +import javax.swing.*;
    5200 +import javax.swing.text.html.*;
    5201 +
    5202 +
    5203 +/**
    5204 + *
    5205 + * @author  kitfox
    5206 + */
    5207 +public class VersionDialog extends javax.swing.JDialog
    5208 +{
    5209 +    public static final long serialVersionUID = 1;
    5210 +   
    5211 +    final boolean verbose;
    5212 +   
    5213 +    /** Creates new form VersionDialog */
    5214 +    public VersionDialog(java.awt.Frame parent, boolean modal, boolean verbose)
    5215 +    {
    5216 +        super(parent, modal);
    5217 +        initComponents();
    5218 +       
    5219 +        this.verbose = verbose;
    5220 +       
    5221 +        textpane_text.setContentType("text/html");
    5222 +       
    5223 +        StringBuffer sb = new StringBuffer();
    5224 +        try
    5225 +        {
    5226 +            URL url = getClass().getResource("/res/help/about/about.html");
    5227 +            if (verbose)
    5228 +            {
    5229 +                System.err.println("" + getClass() + " trying to load about html " + url);
    5230 +            }
    5231 +           
    5232 +            BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
    5233 +            while (true)
    5234 +            {
    5235 +                String line = reader.readLine();
    5236 +                if (line == null) break;
    5237 +                sb.append(line);
    5238 +            }
    5239 +           
    5240 +            textpane_text.setText(sb.toString());
    5241 +        }
    5242 +        catch (Exception e)
    5243 +        {
    5244 +            e.printStackTrace();
    5245 +        }
    5246 +       
    5247 +    }
    5248 +   
    5249 +    /** This method is called from within the constructor to
    5250 +     * initialize the form.
    5251 +     * WARNING: Do NOT modify this code. The content of this method is
    5252 +     * always regenerated by the Form Editor.
    5253 +     */
    5254 +    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    5255 +    private void initComponents()
    5256 +    {
    5257 +        jPanel1 = new javax.swing.JPanel();
    5258 +        textpane_text = new javax.swing.JTextPane();
    5259 +        jPanel2 = new javax.swing.JPanel();
    5260 +        bn_close = new javax.swing.JButton();
    5261 +
    5262 +        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
    5263 +        setTitle("About SVG Salamander");
    5264 +        jPanel1.setLayout(new java.awt.BorderLayout());
    5265 +
    5266 +        textpane_text.setEditable(false);
    5267 +        textpane_text.setPreferredSize(new java.awt.Dimension(400, 300));
    5268 +        jPanel1.add(textpane_text, java.awt.BorderLayout.CENTER);
    5269 +
    5270 +        getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
    5271 +
    5272 +        bn_close.setText("Close");
    5273 +        bn_close.addActionListener(new java.awt.event.ActionListener()
    5274 +        {
    5275 +            public void actionPerformed(java.awt.event.ActionEvent evt)
    5276 +            {
    5277 +                bn_closeActionPerformed(evt);
    5278 +            }
    5279 +        });
    5280 +
    5281 +        jPanel2.add(bn_close);
    5282 +
    5283 +        getContentPane().add(jPanel2, java.awt.BorderLayout.SOUTH);
    5284 +
    5285 +        pack();
    5286 +    }
    5287 +    // </editor-fold>//GEN-END:initComponents
    5288 +
    5289 +    private void bn_closeActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_closeActionPerformed
    5290 +    {//GEN-HEADEREND:event_bn_closeActionPerformed
    5291 +        setVisible(false);
    5292 +        dispose();
    5293 +    }//GEN-LAST:event_bn_closeActionPerformed
    5294 +   
    5295 +    /**
    5296 +     * @param args the command line arguments
    5297 +     */
    5298 +    public static void main(String args[])
    5299 +    {
    5300 +        java.awt.EventQueue.invokeLater(new Runnable()
    5301 +        {
    5302 +            public void run()
    5303 +            {
    5304 +                new VersionDialog(new javax.swing.JFrame(), true, true).setVisible(true);
    5305 +            }
    5306 +        });
    5307 +    }
    5308 +   
    5309 +    // Variables declaration - do not modify//GEN-BEGIN:variables
    5310 +    private javax.swing.JButton bn_close;
    5311 +    private javax.swing.JPanel jPanel1;
    5312 +    private javax.swing.JPanel jPanel2;
    5313 +    private javax.swing.JTextPane textpane_text;
    5314 +    // End of variables declaration//GEN-END:variables
    5315 +   
    5316 +}
    5317 Index: core/src/com/kitfox/svg/app/ant/SVGToImageAntTask.java
    5318 ===================================================================
    5319 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    5320 +++ core/src/com/kitfox/svg/app/ant/SVGToImageAntTask.java      2012-06-17 23:56:57.752545052 +0200
    5321 @@ -0,0 +1,251 @@
    5322 +/*
    5323 + * IndexLoadObjectsAntTask.java
    5324 + *
    5325 + * Created on January 22, 2005, 10:30 AM
    5326 + */
    5327 +
    5328 +package com.kitfox.svg.app.ant;
    5329 +
    5330 +import java.awt.*;
    5331 +import java.awt.image.*;
    5332 +import java.util.*;
    5333 +import java.util.regex.*;
    5334 +import java.io.*;
    5335 +import javax.imageio.*;
    5336 +
    5337 +//import com.kitfox.util.*;
    5338 +//import com.kitfox.util.indexedObject.*;
    5339 +
    5340 +import org.apache.tools.ant.*;
    5341 +import org.apache.tools.ant.types.*;
    5342 +
    5343 +import com.kitfox.svg.app.beans.*;
    5344 +import com.kitfox.svg.*;
    5345 +import com.kitfox.svg.xml.ColorTable;
    5346 +
    5347 +/**
    5348 + * <p>Translates a group of SVG files into images.</p>
    5349 + *
    5350 + * <p>Parameters:</p>
    5351 + * <p><ul>
    5352 + * <li/>destDir - If present, specifices a directory to write SVG files to.  Otherwise
    5353 + * writes images to directory SVG file was found in
    5354 + * verbose - If true, prints processing information to the console
    5355 + * <li/>format - File format for output images.  The java core javax.imageio.ImageIO
    5356 + * class is used for creating images, so format strings will depend on what
    5357 + * files your system is configured to handle.  By default, "gif", "jpg" and "png"
    5358 + * files are guaranteed to be present.  If omitted, "png" is used by default.
    5359 + * <li/>backgroundColor - Optional background color.  Color can be specified as a standard
    5360 + * HTML color.  That is, as the name of a standard color such as "blue" or
    5361 + * "limegreen", using the # notaion as in #ff00ff for magenta, or in rgb format
    5362 + * listing the components as in rgb(255, 192, 192) for pink.  If omitted,
    5363 + * background is transparent.
    5364 + * <li/>antiAlias - If set, shapes are drawn using antialiasing.  Defaults to true.
    5365 + * <li/>interpolation - String describing image interpolation alrogithm.  Can
    5366 + * be one of "nearest neighbor", "bilinear" or "bicubic".  Defaults to "bicubic".
    5367 + * <li/>width - If greater than 0, determines the width of the written image.  Otherwise,
    5368 + * the width is obtained from the SVG document.  Defaults to -1;
    5369 + * <li/>height - If greater than 0, determines the height of the written image.  Otherwise,
    5370 + * the height is obtained from the SVG document.  Defaults to -1.
    5371 + * <li/>sizeToFit - If true and the width and height of the output image differ
    5372 + * from that of the SVG image, the valid area of the SVG image will be resized
    5373 + * to fit the specified size.
    5374 + * <li/>verbose - IF true, prints out diagnostic infromation about processing. 
    5375 + * Defaults to false.
    5376 + * </ul></p>
    5377 + *
    5378 + * Example:
    5379 + * &lt;SVGToImage destDir="${index.java}" format="jpg" verbose="true"&gt;
    5380 + *    &lt;fileset dir="${dir1}"&gt;
    5381 + *        &lt;include name="*.svg"/&gt;
    5382 + *    &lt;/fileset&gt;
    5383 + *    &lt;fileset dir="${dir2}"&gt;
    5384 + *        &lt;include name="*.svg"/&gt;
    5385 + *    &lt;/fileset&gt;
    5386 + * &lt;/SVGToImage&gt;
    5387 + *
    5388 + *
    5389 + *
    5390 + * @author kitfox
    5391 + */
    5392 +public class SVGToImageAntTask extends Task
    5393 +{
    5394 +    private ArrayList filesets = new ArrayList();
    5395 +    boolean verbose = false;
    5396 +    File destDir;
    5397 +    private String format = "png";
    5398 +    Color backgroundColor = null;
    5399 +    int width = -1;
    5400 +    int height = -1;
    5401 +    boolean antiAlias = true;
    5402 +    String interpolation = "bicubic";
    5403 +    boolean clipToViewBox = false;
    5404 +    boolean sizeToFit = true;
    5405 +   
    5406 +    /** Creates a new instance of IndexLoadObjectsAntTask */
    5407 +    public SVGToImageAntTask()
    5408 +    {
    5409 +    }
    5410 +   
    5411 +   
    5412 +    public String getFormat()
    5413 +    {
    5414 +        return format;
    5415 +    }
    5416 +   
    5417 +    public void setFormat(String format)
    5418 +    {
    5419 +        this.format = format;
    5420 +    }
    5421 +   
    5422 +    public void setBackgroundColor(String bgColor)
    5423 +    {
    5424 +        this.backgroundColor = ColorTable.parseColor(bgColor);
    5425 +    }
    5426 +   
    5427 +    public void setHeight(int height)
    5428 +    {
    5429 +        this.height = height;
    5430 +    }
    5431 +   
    5432 +    public void setWidth(int width)
    5433 +    {
    5434 +        this.width = width;
    5435 +    }
    5436 +   
    5437 +    public void setAntiAlias(boolean antiAlias)
    5438 +    {
    5439 +        this.antiAlias = antiAlias;
    5440 +    }
    5441 +   
    5442 +    public void setInterpolation(String interpolation)
    5443 +    {
    5444 +        this.interpolation = interpolation;
    5445 +    }
    5446 +   
    5447 +    public void setSizeToFit(boolean sizeToFit)
    5448 +    {
    5449 +        this.sizeToFit = sizeToFit;
    5450 +    }
    5451 +   
    5452 +    public void setClipToViewBox(boolean clipToViewBox)
    5453 +    {
    5454 +        this.clipToViewBox = clipToViewBox;
    5455 +    }
    5456 +   
    5457 +    public void setVerbose(boolean verbose)
    5458 +    {
    5459 +        this.verbose = verbose;
    5460 +    }
    5461 +   
    5462 +    public void setDestDir(File destDir)
    5463 +    {
    5464 +        this.destDir = destDir;
    5465 +    }
    5466 +   
    5467 +    /**
    5468 +     * Adds a set of files.
    5469 +     */
    5470 +    public void addFileset(FileSet set)
    5471 +    {
    5472 +        filesets.add(set);
    5473 +    }
    5474 +   
    5475 +   
    5476 +   
    5477 +    public void execute()
    5478 +    {
    5479 +        if (verbose) log("Building SVG images");
    5480 +       
    5481 +        for (Iterator it = filesets.iterator(); it.hasNext();)
    5482 +        {
    5483 +            FileSet fs = (FileSet)it.next();
    5484 +            FileScanner scanner = fs.getDirectoryScanner(getProject());
    5485 +            String[] files = scanner.getIncludedFiles();
    5486 +           
    5487 +            try
    5488 +            {
    5489 +                File basedir = scanner.getBasedir();
    5490 +               
    5491 +                if (verbose) log("Scaning " + basedir);
    5492 +               
    5493 +                for (int i = 0; i < files.length; i++)
    5494 +                {
    5495 +//System.out.println("File " + files[i]);
    5496 +//System.out.println("BaseDir " + basedir);
    5497 +                    translate(basedir, files[i]);
    5498 +                }
    5499 +            }
    5500 +            catch (Exception e)
    5501 +            {
    5502 +                throw new BuildException(e);
    5503 +            }
    5504 +        }
    5505 +    }
    5506 +   
    5507 +    private void translate(File baseDir, String shortName) throws BuildException
    5508 +    {
    5509 +        File source = new File(baseDir, shortName);
    5510 +       
    5511 +        if (verbose) log("Reading file: " + source);
    5512 +       
    5513 +        Matcher matchName = Pattern.compile("(.*)\\.svg", Pattern.CASE_INSENSITIVE).matcher(shortName);
    5514 +        if (matchName.matches())
    5515 +        {
    5516 +            shortName = matchName.group(1);
    5517 +        }
    5518 +        shortName += "." + format;
    5519 +       
    5520 +        SVGIcon icon = new SVGIcon();
    5521 +        icon.setSvgURI(source.toURI());
    5522 +        icon.setAntiAlias(antiAlias);
    5523 +        if (interpolation.equals("nearest neighbor"))
    5524 +        {
    5525 +            icon.setInterpolation(SVGIcon.INTERP_NEAREST_NEIGHBOR);
    5526 +        }
    5527 +        else if (interpolation.equals("bilinear"))
    5528 +        {
    5529 +            icon.setInterpolation(SVGIcon.INTERP_BILINEAR);
    5530 +        }
    5531 +        else if (interpolation.equals("bicubic"))
    5532 +        {
    5533 +            icon.setInterpolation(SVGIcon.INTERP_BICUBIC);
    5534 +        }
    5535 +       
    5536 +        int iconWidth = width > 0 ? width : icon.getIconWidth();
    5537 +        int iconHeight = height > 0 ? height : icon.getIconHeight();
    5538 +        icon.setClipToViewbox(clipToViewBox);
    5539 +        icon.setPreferredSize(new Dimension(iconWidth, iconHeight));
    5540 +        icon.setScaleToFit(sizeToFit);
    5541 +        BufferedImage image = new BufferedImage(iconWidth, iconHeight, BufferedImage.TYPE_INT_ARGB);
    5542 +        Graphics2D g = image.createGraphics();
    5543 +       
    5544 +        if (backgroundColor != null)
    5545 +        {
    5546 +            g.setColor(backgroundColor);
    5547 +            g.fillRect(0, 0, iconWidth, iconHeight);
    5548 +        }
    5549 +       
    5550 +        g.setClip(0, 0, iconWidth, iconHeight);
    5551 +//        g.fillRect(10, 10, 100, 100);
    5552 +        icon.paintIcon(null, g, 0, 0);
    5553 +        g.dispose();
    5554 +       
    5555 +        File outFile = destDir == null ? new File(baseDir, shortName) : new File(destDir, shortName);
    5556 +        if (verbose) log("Writing file: " + outFile);
    5557 +       
    5558 +        try
    5559 +        {
    5560 +            ImageIO.write(image, format, outFile);
    5561 +        }
    5562 +        catch (IOException e)
    5563 +        {
    5564 +            log("Error writing image: " + e.getMessage());
    5565 +            throw new BuildException(e);
    5566 +        }
    5567 +       
    5568 +       
    5569 +        SVGCache.getSVGUniverse().clear();
    5570 +    }
    5571 +   
    5572 +}
    5573 Index: core/src/com/kitfox/svg/app/beans/ProportionalLayoutPanel.java
    5574 ===================================================================
    5575 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    5576 +++ core/src/com/kitfox/svg/app/beans/ProportionalLayoutPanel.java      2012-06-17 23:56:57.784545052 +0200
    5577 @@ -0,0 +1,91 @@
    5578 +/*
    5579 + * ProportionalLayoutPanel.java
    5580 + *
    5581 + * Created on May 7, 2005, 4:15 AM
    5582 + */
    5583 +
    5584 +package com.kitfox.svg.app.beans;
    5585 +
    5586 +import java.awt.*;
    5587 +import java.util.*;
    5588 +import javax.swing.*;
    5589 +
    5590 +/**
    5591 + * Panel based on the null layout.  Allows editing with absolute layout.  When
    5592 + * instanced, records layout dimensions of all subcomponents.  Then, if the
    5593 + * panel is ever resized, scales all children to fit new size.
    5594 + *
    5595 + * @author  kitfox
    5596 + */
    5597 +public class ProportionalLayoutPanel extends javax.swing.JPanel
    5598 +{
    5599 +    public static final long serialVersionUID = 1;
    5600 +
    5601 +    //Margins to leave on sides of panel, expressed in fractions [0 1]
    5602 +    float topMargin;
    5603 +    float bottomMargin;
    5604 +    float leftMargin;
    5605 +    float rightMargin;
    5606 +   
    5607 +    /** Creates new form ProportionalLayoutPanel */
    5608 +    public ProportionalLayoutPanel()
    5609 +    {
    5610 +        initComponents();
    5611 +    }
    5612 +   
    5613 +    public void addNotify()
    5614 +    {
    5615 +        super.addNotify();
    5616 +       
    5617 +        Rectangle rect = this.getBounds();
    5618 +        JOptionPane.showMessageDialog(this, "" + rect);
    5619 +    }
    5620 +   
    5621 +   
    5622 +    /** This method is called from within the constructor to
    5623 +     * initialize the form.
    5624 +     * WARNING: Do NOT modify this code. The content of this method is
    5625 +     * always regenerated by the Form Editor.
    5626 +     */
    5627 +    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    5628 +    private void initComponents()
    5629 +    {
    5630 +        jPanel1 = new javax.swing.JPanel();
    5631 +
    5632 +        setLayout(null);
    5633 +
    5634 +        addComponentListener(new java.awt.event.ComponentAdapter()
    5635 +        {
    5636 +            public void componentResized(java.awt.event.ComponentEvent evt)
    5637 +            {
    5638 +                formComponentResized(evt);
    5639 +            }
    5640 +            public void componentShown(java.awt.event.ComponentEvent evt)
    5641 +            {
    5642 +                formComponentShown(evt);
    5643 +            }
    5644 +        });
    5645 +
    5646 +        add(jPanel1);
    5647 +        jPanel1.setBounds(80, 90, 280, 160);
    5648 +
    5649 +    }
    5650 +    // </editor-fold>//GEN-END:initComponents
    5651 +
    5652 +    private void formComponentShown(java.awt.event.ComponentEvent evt)//GEN-FIRST:event_formComponentShown
    5653 +    {//GEN-HEADEREND:event_formComponentShown
    5654 +        JOptionPane.showMessageDialog(this, "" + getWidth() + ", " + getHeight());
    5655 +
    5656 +    }//GEN-LAST:event_formComponentShown
    5657 +
    5658 +    private void formComponentResized(java.awt.event.ComponentEvent evt)//GEN-FIRST:event_formComponentResized
    5659 +    {//GEN-HEADEREND:event_formComponentResized
    5660 +// TODO add your handling code here:
    5661 +    }//GEN-LAST:event_formComponentResized
    5662 +   
    5663 +   
    5664 +    // Variables declaration - do not modify//GEN-BEGIN:variables
    5665 +    private javax.swing.JPanel jPanel1;
    5666 +    // End of variables declaration//GEN-END:variables
    5667 +   
    5668 +}
    5669 Index: core/src/com/kitfox/svg/app/beans/SVGPanel.java
    5670 ===================================================================
    5671 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    5672 +++ core/src/com/kitfox/svg/app/beans/SVGPanel.java     2012-06-17 23:56:57.784545052 +0200
    5673 @@ -0,0 +1,243 @@
    5674 +/*
    5675 + * SVGIcon.java
    5676 + *
    5677 + * Created on April 21, 2005, 10:43 AM
    5678 + */
    5679 +
    5680 +package com.kitfox.svg.app.beans;
    5681 +
    5682 +import javax.swing.*;
    5683 +import java.awt.*;
    5684 +import java.awt.geom.*;
    5685 +import java.net.*;
    5686 +import java.beans.*;
    5687 +
    5688 +import com.kitfox.svg.*;
    5689 +
    5690 +/**
    5691 + *
    5692 + * @author  kitfox
    5693 + */
    5694 +public class SVGPanel extends JPanel
    5695 +{
    5696 +    public static final long serialVersionUID = 1;
    5697 +
    5698 +
    5699 +    SVGUniverse svgUniverse = SVGCache.getSVGUniverse();
    5700 +   
    5701 +    private boolean antiAlias;
    5702 +   
    5703 +//    private String svgPath;
    5704 +    URI svgURI;
    5705 +
    5706 +    private boolean scaleToFit;
    5707 +    AffineTransform scaleXform = new AffineTransform();
    5708 +   
    5709 +    /** Creates new form SVGIcon */
    5710 +    public SVGPanel()
    5711 +    {
    5712 +        initComponents();
    5713 +    }
    5714 +       
    5715 +    public int getSVGHeight()
    5716 +    {
    5717 +        if (scaleToFit) return getPreferredSize().height;
    5718 +       
    5719 +        SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
    5720 +        if (diagram == null) return 0;
    5721 +        return (int)diagram.getHeight();
    5722 +    }
    5723 +   
    5724 +    public int getSVGWidth()
    5725 +    {
    5726 +        if (scaleToFit) return getPreferredSize().width;
    5727 +       
    5728 +        SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
    5729 +        if (diagram == null) return 0;
    5730 +        return (int)diagram.getWidth();
    5731 +    }
    5732 +   
    5733 +//          Draw the icon at the specified location.
    5734 +    public void paintComponent(Graphics gg)
    5735 +    {
    5736 +        super.paintComponent(gg);
    5737 +       
    5738 +        Graphics2D g = (Graphics2D)gg;
    5739 +       
    5740 +        Object oldAliasHint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
    5741 +        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
    5742 +
    5743 +       
    5744 +        SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
    5745 +        if (diagram == null) return;
    5746 +       
    5747 +        if (!scaleToFit)
    5748 +        {
    5749 +            try
    5750 +            {
    5751 +                diagram.render(g);
    5752 +                g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAliasHint);
    5753 +            }
    5754 +            catch (SVGException e)
    5755 +            {
    5756 +                throw new RuntimeException(e);
    5757 +            }
    5758 +            return;
    5759 +        }
    5760 +       
    5761 +        Dimension dim = getSize();
    5762 +        final int width = dim.width;
    5763 +        final int height = dim.height;
    5764 +//        int width = getWidth();
    5765 +//        int height = getHeight();
    5766 +       
    5767 +//        if (width == 0 || height == 0)
    5768 +//        {
    5769 +//           //Chances are we're rendering offscreen
    5770 +//            Dimension dim = getSize();
    5771 +//            width = dim.width;
    5772 +//            height = dim.height;
    5773 +//            return;
    5774 +//        }
    5775 +       
    5776 +//        g.setClip(0, 0, dim.width, dim.height);
    5777 +
    5778 +           
    5779 +        final Rectangle2D.Double rect = new Rectangle2D.Double();
    5780 +        diagram.getViewRect(rect);
    5781 +       
    5782 +        scaleXform.setToScale(width / rect.width, height / rect.height);
    5783 +       
    5784 +        AffineTransform oldXform = g.getTransform();
    5785 +        g.transform(scaleXform);
    5786 +
    5787 +        try
    5788 +        {
    5789 +            diagram.render(g);
    5790 +        }
    5791 +        catch (SVGException e)
    5792 +        {
    5793 +            throw new RuntimeException(e);
    5794 +        }
    5795 +       
    5796 +        g.setTransform(oldXform);
    5797 +       
    5798 +        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAliasHint);
    5799 +    }
    5800 +   
    5801 +    public SVGUniverse getSvgUniverse()
    5802 +    {
    5803 +        return svgUniverse;
    5804 +    }
    5805 +
    5806 +    public void setSvgUniverse(SVGUniverse svgUniverse)
    5807 +    {
    5808 +        SVGUniverse old = this.svgUniverse;
    5809 +        this.svgUniverse = svgUniverse;
    5810 +        firePropertyChange("svgUniverse", old, svgUniverse);
    5811 +    }
    5812 +
    5813 +    public URI getSvgURI()
    5814 +    {
    5815 +        return svgURI;
    5816 +    }
    5817 +
    5818 +    public void setSvgURI(URI svgURI)
    5819 +    {
    5820 +        URI old = this.svgURI;
    5821 +        this.svgURI = svgURI;
    5822 +        firePropertyChange("svgURI", old, svgURI);
    5823 +    }
    5824 +   
    5825 +    /**
    5826 +     * Most resources your component will want to access will be resources on your classpath. 
    5827 +     * This method will interpret the passed string as a path in the classpath and use
    5828 +     * Class.getResource() to determine the URI of the SVG.
    5829 +     */
    5830 +    public void setSvgResourcePath(String resourcePath) throws SVGException
    5831 +    {
    5832 +        URI old = this.svgURI;
    5833 +       
    5834 +        try
    5835 +        {
    5836 +            svgURI = new URI(getClass().getResource(resourcePath).toString());
    5837 +//System.err.println("SVGPanel: new URI " + svgURI + " from path " + resourcePath);
    5838 +           
    5839 +            firePropertyChange("svgURI", old, svgURI);
    5840 +           
    5841 +            repaint();
    5842 +        }
    5843 +        catch (Exception e)
    5844 +        {
    5845 +            throw new SVGException("Could not resolve path " + resourcePath, e);
    5846 +//            svgURI = old;
    5847 +        }
    5848 +    }
    5849 +   
    5850 +    public boolean isScaleToFit()
    5851 +    {
    5852 +        return scaleToFit;
    5853 +    }
    5854 +
    5855 +    public void setScaleToFit(boolean scaleToFit)
    5856 +    {
    5857 +        boolean old = this.scaleToFit;
    5858 +        this.scaleToFit = scaleToFit;
    5859 +        firePropertyChange("scaleToFit", old, scaleToFit);
    5860 +    }
    5861 +   
    5862 +    /**
    5863 +     * @return true if antiAliasing is turned on.
    5864 +     * @deprecated
    5865 +     */
    5866 +    public boolean getUseAntiAlias()
    5867 +    {
    5868 +        return getAntiAlias();
    5869 +    }
    5870 +
    5871 +    /**
    5872 +     * @param antiAlias true to use antiAliasing.
    5873 +     * @deprecated
    5874 +     */
    5875 +    public void setUseAntiAlias(boolean antiAlias)
    5876 +    {
    5877 +        setAntiAlias(antiAlias);
    5878 +    }
    5879 +   
    5880 +    /**
    5881 +     * @return true if antiAliasing is turned on.
    5882 +     */
    5883 +    public boolean getAntiAlias()
    5884 +    {
    5885 +        return antiAlias;
    5886 +    }
    5887 +
    5888 +    /**
    5889 +     * @param antiAlias true to use antiAliasing.
    5890 +     */
    5891 +    public void setAntiAlias(boolean antiAlias)
    5892 +    {
    5893 +        boolean old = this.antiAlias;
    5894 +        this.antiAlias = antiAlias;
    5895 +        firePropertyChange("antiAlias", old, antiAlias);
    5896 +    }
    5897 +   
    5898 +    /** This method is called from within the constructor to
    5899 +     * initialize the form.
    5900 +     * WARNING: Do NOT modify this code. The content of this method is
    5901 +     * always regenerated by the Form Editor.
    5902 +     */
    5903 +    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    5904 +    private void initComponents()
    5905 +    {
    5906 +
    5907 +        setLayout(new java.awt.BorderLayout());
    5908 +
    5909 +    }
    5910 +    // </editor-fold>//GEN-END:initComponents
    5911 +   
    5912 +   
    5913 +    // Variables declaration - do not modify//GEN-BEGIN:variables
    5914 +    // End of variables declaration//GEN-END:variables
    5915 +   
    5916 +}
    5917 Index: core/src/com/kitfox/svg/app/data/HandlerFactory.java
    5918 ===================================================================
    5919 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    5920 +++ core/src/com/kitfox/svg/app/data/HandlerFactory.java        2012-06-17 23:56:57.784545052 +0200
    5921 @@ -0,0 +1,27 @@
    5922 +/*
    5923 + * To change this template, choose Tools | Templates
    5924 + * and open the template in the editor.
    5925 + */
    5926 +
    5927 +package com.kitfox.svg.app.data;
    5928 +
    5929 +import java.net.URLStreamHandler;
    5930 +import java.net.URLStreamHandlerFactory;
    5931 +
    5932 +/**
    5933 + *
    5934 + * @author kitfox
    5935 + */
    5936 +public class HandlerFactory implements URLStreamHandlerFactory
    5937 +{
    5938 +    static Handler handler = new Handler();
    5939 +
    5940 +    public URLStreamHandler createURLStreamHandler(String protocol)
    5941 +    {
    5942 +        if ("data".equals(protocol))
    5943 +        {
    5944 +            return handler;
    5945 +        }
    5946 +        return null;
    5947 +    }
    5948 +}
  • trunk/src/com/kitfox/svg/ClipPath.java

    r6002 r7676  
    131131     * all attributes with track information.
    132132     *
     133     * @param curTime
    133134     * @return - true if this node has changed state as a result of the time
    134135     * update
     136     * @throws com.kitfox.svg.SVGException
    135137     */
    136138    public boolean updateTime(double curTime) throws SVGException
     
    160162        }
    161163
     164        for (int i = 0; i < children.size(); ++i)
     165        {
     166            SVGElement ele = (SVGElement) children.get(i);
     167            ele.updateTime(curTime);
     168        }
     169       
    162170        return shapeChange;
    163171    }
  • trunk/src/com/kitfox/svg/Group.java

    r6002 r7676  
    160160        //Do not process offscreen groups
    161161        boolean ignoreClip = diagram.ignoringClipHeuristic();
    162         if (!ignoreClip && outsideClip(g))
    163         {
    164             return;
    165         }
     162//        if (!ignoreClip && outsideClip(g))
     163//        {
     164//            return;
     165//        }
    166166
    167167        beginLayer(g);
     
    271271                RenderableElement rendEle = (RenderableElement) ele;
    272272                Rectangle2D bounds = rendEle.getBoundingBox();
    273                 if (bounds != null)
     273                if (bounds != null && (bounds.getWidth() != 0 || bounds.getHeight() != 0))
    274274                {
    275275                    if (retRect == null)
    276276                    {
    277277                        retRect = bounds;
    278                     } else
     278                    }
     279                    else
    279280                    {
    280                         retRect = retRect.createUnion(bounds);
     281                        if (retRect.getWidth() != 0 || retRect.getHeight() != 0)
     282                        {
     283                            retRect = retRect.createUnion(bounds);
     284                        }
    281285                    }
    282286                }
  • trunk/src/com/kitfox/svg/ImageSVG.java

    r6002 r7676  
    124124                    {
    125125                        Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
    126                             "Could not parse xlink:href", e);
     126                            "Could not parse xlink:href " + src, e);
    127127//                        e.printStackTrace();
    128128                        imageSrc = null;
  • trunk/src/com/kitfox/svg/RadialGradient.java

    r6002 r7676  
    121121        Point2D.Float pt1 = new Point2D.Float(cx, cy);
    122122        Point2D.Float pt2 = new Point2D.Float(fx, fy);
    123         if (pt1.equals(pt2))
    124         {
    125             Color[] colors = getStopColors();
    126             paint = colors.length > 0 ? colors[0] : Color.black;
    127         } else if (gradientUnits == GU_USER_SPACE_ON_USE)
     123        if (gradientUnits == GU_USER_SPACE_ON_USE)
    128124        {
    129125            paint = new com.kitfox.svg.batik.RadialGradientPaint(
  • trunk/src/com/kitfox/svg/SVGDiagram.java

    r6002 r7676  
    103103    public void render(Graphics2D g) throws SVGException
    104104    {
    105         root.render(g);
     105        root.renderToViewport(g);
    106106    }
    107107   
  • trunk/src/com/kitfox/svg/SVGElement.java

    r6002 r7676  
    588588    static public AffineTransform parseSingleTransform(String val) throws SVGException
    589589    {
    590         final Matcher matchWord = Pattern.compile("[-.\\w]+").matcher("");
     590        final Matcher matchWord = Pattern.compile("([a-zA-Z]+|-?\\d+(\\.\\d+)?|-?\\.\\d+)").matcher("");
    591591
    592592        AffineTransform retXform = new AffineTransform();
  • trunk/src/com/kitfox/svg/SVGRoot.java

    r6002 r7676  
    4444import java.awt.Shape;
    4545import java.awt.geom.AffineTransform;
     46import java.awt.geom.NoninvertibleTransformException;
     47import java.awt.geom.Point2D;
    4648import java.awt.geom.Rectangle2D;
     49import java.util.List;
    4750
    4851/**
     
    239242        clipRect.setRect(xx, yy, ww, hh);
    240243
     244//        if (viewBox == null)
     245//        {
     246//            viewXform.setToIdentity();
     247//        }
     248//        else
     249//        {
     250//            //If viewport window is set, we are drawing to entire viewport
     251//            clipRect.setRect(deviceViewport);
     252//           
     253//            viewXform.setToIdentity();
     254//            viewXform.setToTranslation(deviceViewport.x, deviceViewport.y);
     255//            viewXform.scale(deviceViewport.width, deviceViewport.height);
     256//            viewXform.scale(1 / viewBox.width, 1 / viewBox.height);
     257//            viewXform.translate(-viewBox.x, -viewBox.y);
     258//        }
     259    }
     260
     261    public void renderToViewport(Graphics2D g) throws SVGException
     262    {
     263        prepareViewport();
     264
    241265        if (viewBox == null)
    242266        {
     
    245269        else
    246270        {
    247             viewXform.setToTranslation(clipRect.x, clipRect.y);
    248             viewXform.scale(clipRect.width, clipRect.height);
     271            Rectangle deviceViewport = g.getClipBounds();
     272            //If viewport window is set, we are drawing to entire viewport
     273            clipRect.setRect(deviceViewport);
     274           
     275            viewXform.setToIdentity();
     276            viewXform.setToTranslation(deviceViewport.x, deviceViewport.y);
     277            viewXform.scale(deviceViewport.width, deviceViewport.height);
    249278            viewXform.scale(1 / viewBox.width, 1 / viewBox.height);
    250279            viewXform.translate(-viewBox.x, -viewBox.y);
    251280        }
    252     }
    253 
    254     public void render(Graphics2D g) throws SVGException
    255     {
    256         prepareViewport();
    257281       
    258282        AffineTransform cachedXform = g.getTransform();
     
    262286       
    263287        g.setTransform(cachedXform);
     288    }
     289
     290    public void pick(Rectangle2D pickArea, AffineTransform ltw, boolean boundingBox, List retVec) throws SVGException
     291    {
     292        if (viewXform != null)
     293        {
     294            ltw = new AffineTransform(ltw);
     295            ltw.concatenate(viewXform);
     296        }
     297       
     298        super.pick(pickArea, ltw, boundingBox, retVec);
     299    }
     300   
     301    public void pick(Point2D point, boolean boundingBox, List retVec) throws SVGException
     302    {
     303        Point2D xPoint = new Point2D.Double(point.getX(), point.getY());
     304        if (viewXform != null)
     305        {
     306            try
     307            {
     308                viewXform.inverseTransform(point, xPoint);
     309            } catch (NoninvertibleTransformException ex)
     310            {
     311                throw new SVGException(ex);
     312            }
     313        }
     314       
     315        super.pick(xPoint, boundingBox, retVec);
    264316    }
    265317
  • trunk/src/com/kitfox/svg/SVGUniverse.java

    r6617 r7676  
    5555import java.net.URISyntaxException;
    5656import java.net.URL;
    57 import java.net.URLConnection;
    58 import java.net.URLStreamHandler;
     57import java.util.ArrayList;
    5958import java.util.HashMap;
    6059import java.util.Iterator;
     
    389388            {
    390389                //Workaround for resources stored in jars loaded by Webstart.
    391                 //https://bugs.openjdk.java.net/browse/JDK-6753651
     390                //http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6753651
    392391                url = SVGUniverse.class.getResource("xmlBase.getPath()");
    393392            }
     
    627626    }
    628627
    629 //    public static void main(String argv[])
    630 //    {
    631 //        try
    632 //        {
    633 //            URL url = new URL("svgSalamander", "localhost", -1, "abc.svg",
    634 //                    new URLStreamHandler()
    635 //            {
    636 //                protected URLConnection openConnection(URL u)
    637 //                {
    638 //                    return null;
    639 //                }
    640 //            }
    641 //            );
    642 ////            URL url2 = new URL("svgSalamander", "localhost", -1, "abc.svg");
    643 //           
    644 //            //Investigate URI resolution
    645 //            URI uriA, uriB, uriC, uriD, uriE;
    646 //           
    647 //            uriA = new URI("svgSalamander", "/names/mySpecialName", null);
    648 ////            uriA = new URI("http://www.kitfox.com/salamander");
    649 ////            uriA = new URI("svgSalamander://mySpecialName/grape");
    650 //            System.err.println(uriA.toString());
    651 //            System.err.println(uriA.getScheme());
    652 //           
    653 //            uriB = uriA.resolve("#begin");
    654 //            System.err.println(uriB.toString());
    655 //           
    656 //            uriC = uriA.resolve("tree#boing");
    657 //            System.err.println(uriC.toString());
    658 //           
    659 //            uriC = uriA.resolve("../tree#boing");
    660 //            System.err.println(uriC.toString());
    661 //        }
    662 //        catch (Exception e)
    663 //        {
    664 //            Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
    665 //                "Could not parse", e);
    666 //        }
    667 //    }
     628    /**
     629     * Get list of uris of all loaded documents and subdocuments.
     630     * @return
     631     */
     632    public ArrayList getLoadedDocumentURIs()
     633    {
     634        return new ArrayList(loadedDocs.keySet());
     635    }
     636   
     637    /**
     638     * Remove loaded document from cache.
     639     * @param uri
     640     */
     641    public void removeDocument(URI uri)
     642    {
     643        loadedDocs.remove(uri);
     644    }
     645   
    668646    public boolean isVerbose()
    669647    {
  • trunk/src/com/kitfox/svg/ShapeElement.java

    r6002 r7676  
    8787    void pick(Point2D point, boolean boundingBox, List retVec) throws SVGException
    8888    {
    89         StyleAttribute styleAttrib = new StyleAttribute();
     89//        StyleAttribute styleAttrib = new StyleAttribute();
    9090//        if (getStyle(styleAttrib.setName("fill")) && getShape().contains(point))
    9191        if ((boundingBox ? getBoundingBox() : getShape()).contains(point))
  • trunk/src/com/kitfox/svg/Text.java

    r6002 r7676  
    4242import java.awt.geom.AffineTransform;
    4343import java.awt.geom.GeneralPath;
     44import java.awt.geom.Point2D;
    4445import java.awt.geom.Rectangle2D;
    4546import java.util.Iterator;
     
    209210        } else
    210211        {
    211             fontWeight = TXWE_BOLD;
     212            fontWeight = TXWE_NORMAL;
    212213        }
    213214
     
    352353            {
    353354                AffineTransform at = new AffineTransform();
    354                 at.translate(-textPath.getBounds2D().getWidth() / 2, 0);
     355                at.translate(-textPath.getBounds().getWidth() / 2, 0);
    355356                textPath.transform(at);
    356357                break;
     
    359360            {
    360361                AffineTransform at = new AffineTransform();
    361                 at.translate(-textPath.getBounds2D().getWidth(), 0);
     362                at.translate(-textPath.getBounds().getWidth(), 0);
    362363                textPath.transform(at);
    363364                break;
     
    390391            if (obj instanceof String)
    391392            {
    392                 String text = (String) obj;
     393                String text = (String)obj;
     394                text = text.trim();
    393395
    394396                Shape textShape = font.createGlyphVector(frc, text).getOutline(cursorX, cursorY);
     
    415417
    416418
    417                 Tspan tspan = (Tspan) obj;
    418                 tspan.setCursorX(cursorX);
    419                 tspan.setCursorY(cursorY);
    420                 tspan.addShape(textPath);
    421                 cursorX = tspan.getCursorX();
    422                 cursorY = tspan.getCursorY();
     419                Tspan tspan = (Tspan)obj;
     420                Point2D cursor = new Point2D.Float(cursorX, cursorY);
     421//                tspan.setCursorX(cursorX);
     422//                tspan.setCursorY(cursorY);
     423                tspan.appendToShape(textPath, cursor);
     424//                cursorX = tspan.getCursorX();
     425//                cursorY = tspan.getCursorY();
     426                cursorX = (float)cursor.getX();
     427                cursorY = (float)cursor.getY();
    423428
    424429            }
     
    430435            {
    431436                AffineTransform at = new AffineTransform();
    432                 at.translate(-textPath.getBounds2D().getWidth() / 2, 0);
     437                at.translate(-textPath.getBounds().getWidth() / 2, 0);
    433438                textPath.transform(at);
    434439                break;
     
    437442            {
    438443                AffineTransform at = new AffineTransform();
    439                 at.translate(-textPath.getBounds2D().getWidth(), 0);
     444                at.translate(-Math.ceil(textPath.getBounds().getWidth()), 0);
    440445                textPath.transform(at);
    441446                break;
  • trunk/src/com/kitfox/svg/TransformableElement.java

    r6002 r7676  
    7171    public AffineTransform getXForm()
    7272    {
    73         return xform != null ? new AffineTransform(xform) : null;
     73        return xform == null ? null : new AffineTransform(xform);
    7474    }
    7575    /*
  • trunk/src/com/kitfox/svg/Tspan.java

    r6002 r7676  
    4444import java.awt.geom.AffineTransform;
    4545import java.awt.geom.GeneralPath;
     46import java.awt.geom.Point2D;
    4647import java.awt.geom.Rectangle2D;
    4748
     
    6061    float[] rotate = null;
    6162    private String text = "";
    62     float cursorX;
    63     float cursorY;
     63//    float cursorX;
     64//    float cursorY;
    6465
    6566//    Shape tspanShape;
     
    7677    }
    7778
    78     public float getCursorX()
    79     {
    80         return cursorX;
    81     }
    82 
    83     public float getCursorY()
    84     {
    85         return cursorY;
    86     }
    87 
    88     public void setCursorX(float cursorX)
    89     {
    90         this.cursorX = cursorX;
    91     }
    92 
    93     public void setCursorY(float cursorY)
    94     {
    95         this.cursorY = cursorY;
    96     }
     79//    public float getCursorX()
     80//    {
     81//        return cursorX;
     82//    }
     83//
     84//    public float getCursorY()
     85//    {
     86//        return cursorY;
     87//    }
     88//
     89//    public void setCursorX(float cursorX)
     90//    {
     91//        this.cursorX = cursorX;
     92//    }
     93//
     94//    public void setCursorY(float cursorY)
     95//    {
     96//        this.cursorY = cursorY;
     97//    }
    9798    /*
    9899     public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent)
     
    165166    }
    166167
    167     public void addShape(GeneralPath addShape) throws SVGException
    168     {
    169         if (x != null)
    170         {
    171             cursorX = x[0];
    172         } else if (dx != null)
    173         {
    174             cursorX += dx[0];
    175         }
    176 
    177         if (y != null)
    178         {
    179             cursorY = y[0];
    180         } else if (dy != null)
    181         {
    182             cursorY += dy[0];
    183         }
     168    public void appendToShape(GeneralPath addShape, Point2D cursor) throws SVGException
     169    {
     170//        if (x != null)
     171//        {
     172//            cursorX = x[0];
     173//        } else if (dx != null)
     174//        {
     175//            cursorX += dx[0];
     176//        }
     177//
     178//        if (y != null)
     179//        {
     180//            cursorY = y[0];
     181//        } else if (dy != null)
     182//        {
     183//            cursorY += dy[0];
     184//        }
    184185
    185186        StyleAttribute sty = new StyleAttribute();
     
    209210        if (font == null)
    210211        {
    211             addShapeSysFont(addShape, font, fontFamily, fontSize, letterSpacing);
     212            addShapeSysFont(addShape, font, fontFamily, fontSize, letterSpacing, cursor);
    212213            return;
    213214        }
     
    221222        strokeWidthScalar = 1f / fontScale;
    222223
    223         int posPtr = 1;
    224 
    225         for (int i = 0; i < text.length(); i++)
    226         {
     224        float cursorX = (float)cursor.getX();
     225        float cursorY = (float)cursor.getY();
     226   
     227//        int i = 0;
     228
     229        String drawText = this.text;
     230        drawText = drawText.trim();
     231        for (int i = 0; i < drawText.length(); i++)
     232        {
     233            if (x != null && i < x.length)
     234            {
     235                cursorX = x[i];
     236            } else if (dx != null && i < dx.length)
     237            {
     238                cursorX += dx[i];
     239            }
     240           
     241            if (y != null && i < y.length)
     242            {
     243                cursorY = y[i];
     244            } else if (dy != null && i < dy.length)
     245            {
     246                cursorY += dy[i];
     247            }
     248  //          i++;
     249           
    227250            xform.setToIdentity();
    228251            xform.setToTranslation(cursorX, cursorY);
     
    230253            if (rotate != null)
    231254            {
    232                 xform.rotate(rotate[posPtr]);
    233             }
    234 
    235             String unicode = text.substring(i, i + 1);
     255                xform.rotate(rotate[i]);
     256            }
     257
     258            String unicode = drawText.substring(i, i + 1);
    236259            MissingGlyph glyph = font.getGlyph(unicode);
    237260
     
    243266            }
    244267
    245             if (x != null && posPtr < x.length)
    246             {
    247                 cursorX = x[posPtr];
    248                 cursorY = y[posPtr++];
    249             } else if (dx != null && posPtr < dx.length)
    250             {
    251                 cursorX += dx[posPtr];
    252                 cursorY += dy[posPtr++];
    253             }
    254 
    255268            cursorX += fontScale * glyph.getHorizAdvX() + letterSpacing;
    256269        }
    257270
     271        //Save final draw point so calling method knows where to begin next
     272        // text draw
     273        cursor.setLocation(cursorX, cursorY);
    258274        strokeWidthScalar = 1f;
    259275    }
    260276
    261277    private void addShapeSysFont(GeneralPath addShape, Font font,
    262         String fontFamily, float fontSize, float letterSpacing)
    263     {
     278        String fontFamily, float fontSize, float letterSpacing, Point2D cursor)
     279    {
     280
    264281        java.awt.Font sysFont = new java.awt.Font(fontFamily, java.awt.Font.PLAIN, (int) fontSize);
    265282
    266283        FontRenderContext frc = new FontRenderContext(null, true, true);
    267         GlyphVector textVector = sysFont.createGlyphVector(frc, text);
     284        String renderText = this.text.trim();
    268285
    269286        AffineTransform xform = new AffineTransform();
    270287
    271         int posPtr = 1;
    272         for (int i = 0; i < text.length(); i++)
    273         {
     288        float cursorX = (float)cursor.getX();
     289        float cursorY = (float)cursor.getY();
     290//        int i = 0;
     291        for (int i = 0; i < renderText.length(); i++)
     292        {
     293            if (x != null && i < x.length)
     294            {
     295                cursorX = x[i];
     296            } else if (dx != null && i < dx.length)
     297            {
     298                cursorX += dx[i];
     299            }
     300
     301            if (y != null && i < y.length)
     302            {
     303                cursorY = y[i];
     304            } else if (dy != null && i < dy.length)
     305            {
     306                cursorY += dy[i];
     307            }
     308//            i++;
     309           
    274310            xform.setToIdentity();
    275             xform.setToTranslation(cursorX + i * letterSpacing, cursorY);
     311            xform.setToTranslation(cursorX, cursorY);
    276312            if (rotate != null)
    277313            {
     
    279315            }
    280316
    281             String unicode = text.substring(i, i + 1);
    282             Shape glyphOutline = textVector.getGlyphOutline(i);
    283             GlyphMetrics glyphMetrics = textVector.getGlyphMetrics(i);
     317//            String unicode = renderText.substring(i, i + 1);
     318            GlyphVector textVector = sysFont.createGlyphVector(frc, renderText.substring(i, i + 1));
     319            Shape glyphOutline = textVector.getGlyphOutline(0);
     320            GlyphMetrics glyphMetrics = textVector.getGlyphMetrics(0);
    284321
    285322            glyphOutline = xform.createTransformedShape(glyphOutline);
    286323            addShape.append(glyphOutline, false);
    287324
    288             if (x != null && posPtr < x.length)
    289             {
    290                 cursorX = x[posPtr];
    291                 cursorY = y[posPtr++];
    292             } else if (dx != null && posPtr < dx.length)
    293             {
    294                 cursorX += dx[posPtr];
    295                 cursorY += dy[posPtr++];
    296             }
    297         }
     325
     326//            cursorX += fontScale * glyph.getHorizAdvX() + letterSpacing;
     327            cursorX += glyphMetrics.getAdvance() + letterSpacing;
     328        }
     329       
     330        cursor.setLocation(cursorX, cursorY);
    298331    }
    299332
    300333    public void render(Graphics2D g) throws SVGException
    301334    {
     335        float cursorX = 0;
     336        float cursorY = 0;
     337   
    302338        if (x != null)
    303339        {
     
    385421    protected void renderSysFont(Graphics2D g, java.awt.Font font) throws SVGException
    386422    {
     423        float cursorX = 0;
     424        float cursorY = 0;
     425   
    387426        int posPtr = 1;
    388427        FontRenderContext frc = g.getFontRenderContext();
  • trunk/src/com/kitfox/svg/Use.java

    r6002 r7676  
    124124        }
    125125
    126         RenderableElement rendEle = (RenderableElement) ref;
     126        RenderableElement rendEle = (RenderableElement)ref;
    127127        rendEle.pushParentContext(this);
    128128        rendEle.render(g);
  • trunk/src/com/kitfox/svg/app/beans/SVGIcon.java

    r6002 r7676  
    5151{
    5252    public static final long serialVersionUID = 1;
    53    
    54     private PropertyChangeSupport changes = new PropertyChangeSupport(this);
     53
     54    public static final String PROP_AUTOSIZE = "PROP_AUTOSIZE";
     55   
     56    private final PropertyChangeSupport changes = new PropertyChangeSupport(this);
    5557   
    5658    SVGUniverse svgUniverse = SVGCache.getSVGUniverse();
     
    6365    private boolean clipToViewbox;
    6466   
    65 //    private String svgPath;
    6667    URI svgURI;
    6768   
    68     private boolean scaleToFit;
     69//    private boolean scaleToFit;
    6970    AffineTransform scaleXform = new AffineTransform();
    70    
    71 //    Dimension preferredSize = new Dimension(100, 100);
     71
     72    public static final int AUTOSIZE_NONE = 0;
     73    public static final int AUTOSIZE_HORIZ = 1;
     74    public static final int AUTOSIZE_VERT = 2;
     75    public static final int AUTOSIZE_BESTFIT = 3;
     76    public static final int AUTOSIZE_STRETCH = 4;
     77    private int autosize = AUTOSIZE_NONE;
     78   
    7279    Dimension preferredSize;
    7380   
     
    9299    public int getIconHeight()
    93100    {
    94         if (scaleToFit && preferredSize != null)
     101        if (preferredSize != null &&
     102                (autosize == AUTOSIZE_VERT || autosize == AUTOSIZE_STRETCH
     103                || autosize == AUTOSIZE_BESTFIT))
    95104        {
    96105            return preferredSize.height;
     
    110119    public int getIconWidth()
    111120    {
    112         if (scaleToFit && preferredSize != null)
     121        if (preferredSize != null &&
     122                (autosize == AUTOSIZE_HORIZ || autosize == AUTOSIZE_STRETCH
     123                || autosize == AUTOSIZE_BESTFIT))
    113124        {
    114125            return preferredSize.width;
     
    172183       
    173184       
    174        
    175         if (!scaleToFit)
     185        if (autosize == AUTOSIZE_NONE)
    176186        {
    177187            try
     
    210220       
    211221       
    212         final Rectangle2D.Double rect = new Rectangle2D.Double();
    213         diagram.getViewRect(rect);
    214        
    215         scaleXform.setToScale(width / rect.width, height / rect.height);
     222//        final Rectangle2D.Double rect = new Rectangle2D.Double();
     223//        diagram.getViewRect(rect);
     224//       
     225//        scaleXform.setToScale(width / rect.width, height / rect.height);
     226        double diaWidth = diagram.getWidth();
     227        double diaHeight = diagram.getHeight();
     228       
     229        double scaleW = 1;
     230        double scaleH = 1;
     231        if (autosize == AUTOSIZE_BESTFIT)
     232        {
     233            scaleW = scaleH = (height / diaHeight < width / diaWidth)
     234                    ? height / diaHeight : width / diaWidth;
     235        }
     236        else if (autosize == AUTOSIZE_HORIZ)
     237        {
     238            scaleW = scaleH = width / diaWidth;
     239        }
     240        else if (autosize == AUTOSIZE_VERT)
     241        {
     242            scaleW = scaleH = height / diaHeight;
     243        }
     244        else if (autosize == AUTOSIZE_STRETCH)
     245        {
     246            scaleW = width / diaWidth;
     247            scaleH = height / diaHeight;
     248        }
     249        scaleXform.setToScale(scaleW, scaleH);
    216250       
    217251        AffineTransform oldXform = g.getTransform();
     
    315349     * If this SVG document has a viewbox, if scaleToFit is set, will scale the viewbox to match the
    316350     * preferred size of this icon
     351     * @deprecated
     352     * @return
    317353     */
    318354    public boolean isScaleToFit()
    319355    {
    320         return scaleToFit;
    321     }
    322    
     356        return autosize == AUTOSIZE_STRETCH;
     357    }
     358   
     359    /**
     360     * @deprecated
     361     * @return
     362     */
    323363    public void setScaleToFit(boolean scaleToFit)
    324364    {
    325         boolean old = this.scaleToFit;
    326         this.scaleToFit = scaleToFit;
    327         changes.firePropertyChange("scaleToFit", old, scaleToFit);
     365        setAutosize(AUTOSIZE_STRETCH);
     366//        boolean old = this.scaleToFit;
     367//        this.scaleToFit = scaleToFit;
     368//        firePropertyChange("scaleToFit", old, scaleToFit);
    328369    }
    329370   
     
    429470        this.clipToViewbox = clipToViewbox;
    430471    }
    431    
     472
     473    /**
     474     * @return the autosize
     475     */
     476    public int getAutosize()
     477    {
     478        return autosize;
     479    }
     480
     481    /**
     482     * @param autosize the autosize to set
     483     */
     484    public void setAutosize(int autosize)
     485    {
     486        int oldAutosize = this.autosize;
     487        this.autosize = autosize;
     488        changes.firePropertyChange(PROP_AUTOSIZE, oldAutosize, autosize);
     489    }
     490       
    432491}
  • trunk/src/com/kitfox/svg/pattern/PatternPaintContext.java

    r6002 r7676  
    9797    {
    9898//System.err.println("" + x + ", " + y + ", " + w + ", " + h);
    99         if (buf == null || buf.getWidth() != w || buf.getHeight() != buf.getHeight())
     99        if (buf == null || buf.getWidth() != w || buf.getHeight() != h)
    100100        {
    101101            buf = new BufferedImage(w, h, source.getType());
  • trunk/src/com/kitfox/svg/xml/ColorTable.java

    r6002 r7676  
    225225        Color retVal = null;
    226226
     227        if ("".equals(val))
     228        {
     229            return null;
     230        }
     231       
    227232        if (val.charAt(0) == '#')
    228233        {
  • trunk/src/com/kitfox/svg/xml/cpx/CPXInputStream.java

    r6002 r7676  
    3939import com.kitfox.svg.SVGConst;
    4040import java.io.*;
    41 import java.util.*;
    4241import java.util.zip.*;
    4342import java.security.*;
    4443import java.util.logging.Level;
    4544import java.util.logging.Logger;
    46 import javax.crypto.*;
    4745
    4846/**
  • trunk/src/com/kitfox/svg/xml/cpx/CPXOutputStream.java

    r6002 r7676  
    3939import java.io.*;
    4040import java.util.zip.*;
    41 import java.security.*;
    42 import javax.crypto.*;
    4341
    4442/**
Note: See TracChangeset for help on using the changeset viewer.