Commits

Joseph Walton committed 5f2fa4b

Use the animated version.

  • Participants
  • Parent commits 147fdf2

Comments (0)

Files changed (2)

File an-introduction-to-the-atlassian-platform.svg

 <!-- Created with Inkscape (http://www.inkscape.org/) -->
 
 <svg
+   xmlns:ns1="http://sozi.baierouge.fr"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:cc="http://creativecommons.org/ns#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="3000"
-   height="1900"
-   id="svg2"
-   version="1.1"
+   sodipodi:docname="in-progress.svg"
    inkscape:version="0.48.2 r9819"
-   sodipodi:docname="in-progress.svg">
+   version="1.1"
+   id="svg2"
+   height="1900"
+   width="3000">
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="6.8782668"
+     inkscape:cx="2866.9962"
+     inkscape:cy="589.68928"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1717"
+     inkscape:window-height="1073"
+     inkscape:window-x="109"
+     inkscape:window-y="76"
+     inkscape:window-maximized="0" />
   <defs
      id="defs4">
     <linearGradient
     </marker>
     <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient6190"
-       id="linearGradient6196"
+       xlink:href="#linearGradient6190-6"
+       id="linearGradient6196-1"
        x1="2202.1328"
        y1="1719.1826"
        x2="2202.6377"
        y2="1863.6344"
        gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient6190-6">
+      <stop
+         style="stop-color:#949494;stop-opacity:1;"
+         offset="0"
+         id="stop6192-6" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop6194-2" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="matrix(0.24924829,0,0,0.24924829,-33.934561,-908.53831)"
+       y2="1863.6344"
+       x2="2202.6377"
+       y1="1719.1826"
+       x1="2202.1328"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient5475-0"
+       xlink:href="#linearGradient6190-6-8"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient6190-6-8">
+      <stop
+         style="stop-color:#949494;stop-opacity:1;"
+         offset="0"
+         id="stop6192-6-5" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop6194-2-3" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="translate(0,-847.63782)"
+       y2="1863.6344"
+       x2="2202.6377"
+       y1="1719.1826"
+       x1="2202.1328"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient6670"
+       xlink:href="#linearGradient6190"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="1863.6344"
+       x2="2202.6377"
+       y1="1719.1826"
+       x1="2202.1328"
+       gradientTransform="matrix(0.24924829,0,0,0.24924829,0.38179442,-891.90748)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient6687"
+       xlink:href="#linearGradient6190-6-8"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="1863.6344"
+       x2="2202.6377"
+       y1="1719.1826"
+       x1="2202.1328"
+       gradientTransform="matrix(0.24924829,0,0,0.24924829,-33.934561,-908.53831)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient6690"
+       xlink:href="#linearGradient6190-6"
+       inkscape:collect="always" />
   </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="4.1271969"
-     inkscape:cx="204.16801"
-     inkscape:cy="879.28572"
-     inkscape:document-units="px"
-     inkscape:current-layer="g4830"
-     showgrid="false"
-     fit-margin-top="0"
-     fit-margin-left="0"
-     fit-margin-right="0"
-     fit-margin-bottom="0"
-     inkscape:window-width="1717"
-     inkscape:window-height="1073"
-     inkscape:window-x="174"
-     inkscape:window-y="85"
-     inkscape:window-maximized="0" />
   <metadata
      id="metadata7">
     <rdf:RDF>
      id="layer1"
      transform="translate(0,847.63782)">
     <g
-       id="g4614"
-       transform="matrix(0.84254547,-0.11006567,0.11006567,0.84254547,411.79409,-1194.7307)">
-      <g
-         id="g3876"
-         transform="matrix(0.15060038,0,0,0.15060038,-3.0415328,713.42659)">
-        <text
-           xml:space="preserve"
-           style="font-size:15px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#3999b5;fill-opacity:1;stroke:none;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter Bold"
-           x="100.21388"
+       transform="matrix(0.64920935,0,0,0.64920935,-51.426425,-172.49421)"
+       id="g4217">
+      <text
+         sodipodi:linespacing="125%"
+         id="text3055-8"
+         y="423.24289"
+         x="100.21388"
+         style="font-size:15px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#3999b5;fill-opacity:1;stroke:none;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter Bold"
+         xml:space="preserve"><tspan
            y="423.24289"
-           id="text3055"
-           sodipodi:linespacing="125%"><tspan
-             sodipodi:role="line"
-             id="tspan3057"
-             x="100.21388"
-             y="423.24289">An introduction to</tspan></text>
-        <text
-           xml:space="preserve"
-           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#3999b5;fill-opacity:1;stroke:none;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter Bold"
-           x="97.474167"
+           x="100.21388"
+           id="tspan3057-7"
+           sodipodi:role="line">An introduction to</tspan></text>
+      <text
+         sodipodi:linespacing="125%"
+         id="text3059-02"
+         y="466.52893"
+         x="97.474167"
+         style="font-size:40px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#3999b5;fill-opacity:1;stroke:none;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter Bold"
+         xml:space="preserve"><tspan
            y="466.52893"
-           id="text3059"
-           sodipodi:linespacing="125%"><tspan
-             sodipodi:role="line"
-             id="tspan3061"
-             x="97.474167"
-             y="466.52893">The Atlassian Platform</tspan></text>
-        <text
-           xml:space="preserve"
-           style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter"
-           x="234.35539"
+           x="97.474167"
+           id="tspan3061-1"
+           sodipodi:role="line">The Atlassian Platform</tspan></text>
+      <text
+         sodipodi:linespacing="125%"
+         id="text3835-9"
+         y="523.04218"
+         x="234.35539"
+         style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter"
+         xml:space="preserve"><tspan
            y="523.04218"
-           id="text3835"
-           sodipodi:linespacing="125%"><tspan
-             sodipodi:role="line"
-             id="tspan3837"
-             x="234.35539"
-             y="523.04218">Joseph Walton</tspan><tspan
-             sodipodi:role="line"
-             x="234.35539"
-             y="548.04218"
-             id="tspan3839">ex-bootcamper</tspan></text>
+           x="234.35539"
+           id="tspan3837-8"
+           sodipodi:role="line">Joseph Walton</tspan><tspan
+           id="tspan3839-4"
+           y="548.04218"
+           x="234.35539"
+           sodipodi:role="line">ex-bootcamper</tspan></text>
+      <g
+         id="g4208"
+         transform="matrix(0.6821448,0,0,0.6821448,51.893096,185.50956)">
         <text
            xml:space="preserve"
            style="font-size:15px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter"
            x="689.9342"
            y="601.83417"
-           id="text3841"
+           id="text3841-5"
            sodipodi:linespacing="125%"><tspan
              sodipodi:role="line"
-             id="tspan3843"
+             id="tspan3843-8"
              x="689.9342"
              y="601.83417">Derived from Robin Fernandes's &quot;An introduction to The Atlassian Platform&quot;</tspan><tspan
              sodipodi:role="line"
              x="689.9342"
              y="620.58417"
-             id="tspan3845">Derived from Don's &quot;Plugins State of the Union&quot;</tspan><tspan
+             id="tspan3845-0">Derived from Don's &quot;Plugins State of the Union&quot;</tspan><tspan
              sodipodi:role="line"
              x="689.9342"
              y="639.33417"
-             id="tspan3847" /></text>
+             id="tspan3847-2" /></text>
         <a
-           id="a3853"
+           id="a3853-0"
            xlink:href="http://bit.ly/plugins-union"
            transform="translate(144.45181,-98.99495)"
            style="fill:#2f4e94;fill-opacity:1">
           <text
              sodipodi:linespacing="125%"
-             id="text3849"
+             id="text3849-5"
              y="748.30627"
              x="352.54324"
              style="font-size:15px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#2f4e94;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
              xml:space="preserve"><tspan
                y="748.30627"
                x="352.54324"
-               id="tspan3851"
+               id="tspan3851-8"
                sodipodi:role="line">http://bit.ly/plugins-union</tspan></text>
         </a>
       </g>
-      <path
-         sodipodi:nodetypes="cccccccc"
-         inkscape:connector-curvature="0"
-         id="rect4048"
-         transform="translate(0,552.36218)"
-         d="m -115.34375,181.78125 -18.9375,0 0,85.375 18.9375,0 m 379.03125,0 19.1875,0 0,-85.375 -19.1875,0"
-         style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
-      <text
-         sodipodi:linespacing="125%"
-         id="text3059-0"
-         y="739.62518"
-         x="-102.27916"
-         style="font-size:15px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#3999b5;fill-opacity:1;stroke:none;font-family:Century Schoolbook L;-inkscape-font-specification:Century Schoolbook L Medium"
-         xml:space="preserve"><tspan
-           y="739.62518"
-           x="-102.27916"
-           id="tspan3061-4"
-           sodipodi:role="line">The Atlassian Platform:</tspan></text>
-      <text
-         sodipodi:linespacing="125%"
-         id="text4036"
-         y="763.29456"
-         x="-113.72793"
-         style="font-size:15px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Century Schoolbook L;-inkscape-font-specification:Century Schoolbook L Medium"
-         xml:space="preserve"><tspan
-           id="tspan4040"
-           y="763.29456"
-           x="-113.72793"
-           sodipodi:role="line">A combination of:</tspan><tspan
-           id="tspan4044"
-           y="782.04456"
-           x="-113.72793"
-           sodipodi:role="line">•a framework to host Atlassian plugins</tspan><tspan
-           id="tspan4046"
-           y="800.79456"
-           x="-113.72793"
-           sodipodi:role="line">•a set of libraries &amp; services to support common tasks</tspan></text>
     </g>
+    <rect
+       ry="7.6824002"
+       y="74.45871"
+       x="1.2114763"
+       height="181.72141"
+       width="299.96146"
+       id="rect4234"
+       style="fill:none;stroke:#ababab;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:0.99999999, 1.99999997;stroke-dashoffset:0" />
     <g
        id="g4638"
        transform="matrix(0.62619645,0,0,0.62619645,502.34531,-978.86144)">
     </g>
     <text
        xml:space="preserve"
-       style="font-size:1.65500307px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
-       x="543.37329"
-       y="-319.74451"
+       style="font-size:1.40688956px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+       x="551.06128"
+       y="-319.90118"
        id="text4649-0"
        sodipodi:linespacing="125%"
        transform="matrix(0.98595302,-0.16702286,0.16702286,0.98595302,0,0)"><tspan
          sodipodi:role="line"
          id="tspan4651-3"
-         x="543.37329"
-         y="-319.74451">Despite fundamental differences between products under the</tspan><tspan
+         x="551.06128"
+         y="-319.90118">Despite fundamental differences between products under the</tspan><tspan
          sodipodi:role="line"
-         x="543.37329"
-         y="-317.67575"
+         x="551.06128"
+         y="-318.14258"
          id="tspan4653">covers: different template renderers, persistence libraries, DI</tspan><tspan
          sodipodi:role="line"
-         x="543.37329"
-         y="-315.60699"
+         x="551.06128"
+         y="-316.38394"
          id="tspan4655">frameworks, etc...</tspan></text>
     <g
-       transform="matrix(0.64920935,0,0,0.64920935,-51.426425,-172.49421)"
-       id="g4830">
-      <g
-         id="g4217">
-        <text
-           xml:space="preserve"
-           style="font-size:15px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#3999b5;fill-opacity:1;stroke:none;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter Bold"
-           x="100.21388"
-           y="423.24289"
-           id="text3055-8"
-           sodipodi:linespacing="125%"><tspan
-             sodipodi:role="line"
-             id="tspan3057-7"
-             x="100.21388"
-             y="423.24289">An introduction to</tspan></text>
-        <text
-           xml:space="preserve"
-           style="font-size:40px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#3999b5;fill-opacity:1;stroke:none;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter Bold"
-           x="97.474167"
-           y="466.52893"
-           id="text3059-02"
-           sodipodi:linespacing="125%"><tspan
-             sodipodi:role="line"
-             id="tspan3061-1"
-             x="97.474167"
-             y="466.52893">The Atlassian Platform</tspan></text>
-        <text
-           xml:space="preserve"
-           style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter"
-           x="234.35539"
-           y="523.04218"
-           id="text3835-9"
-           sodipodi:linespacing="125%"><tspan
-             sodipodi:role="line"
-             id="tspan3837-8"
-             x="234.35539"
-             y="523.04218">Joseph Walton</tspan><tspan
-             sodipodi:role="line"
-             x="234.35539"
-             y="548.04218"
-             id="tspan3839-4">ex-bootcamper</tspan></text>
-        <g
-           transform="matrix(0.6821448,0,0,0.6821448,51.893096,185.50956)"
-           id="g4208">
-          <text
-             sodipodi:linespacing="125%"
-             id="text3841-5"
-             y="601.83417"
-             x="689.9342"
-             style="font-size:15px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter"
-             xml:space="preserve"><tspan
-               y="601.83417"
-               x="689.9342"
-               id="tspan3843-8"
-               sodipodi:role="line">Derived from Robin Fernandes's &quot;An introduction to The Atlassian Platform&quot;</tspan><tspan
-               id="tspan3845-0"
-               y="620.58417"
-               x="689.9342"
-               sodipodi:role="line">Derived from Don's &quot;Plugins State of the Union&quot;</tspan><tspan
-               id="tspan3847-2"
-               y="639.33417"
-               x="689.9342"
-               sodipodi:role="line" /></text>
-          <a
-             style="fill:#2f4e94;fill-opacity:1"
-             transform="translate(144.45181,-98.99495)"
-             xlink:href="http://bit.ly/plugins-union"
-             id="a3853-0">
-            <text
-               xml:space="preserve"
-               style="font-size:15px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#2f4e94;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
-               x="352.54324"
-               y="748.30627"
-               id="text3849-5"
-               sodipodi:linespacing="125%"><tspan
-                 sodipodi:role="line"
-                 id="tspan3851-8"
-                 x="352.54324"
-                 y="748.30627">http://bit.ly/plugins-union</tspan></text>
-          </a>
-        </g>
-      </g>
-    </g>
-    <g
        id="g6266">
       <g
          transform="matrix(0.42518032,0,0,0.42518032,250.54829,-310.20881)"
          id="rect4048-3-9"
          d="m 468.6971,-329.83759 -14.39582,0 0,247.752575 14.39582,0 m 288.13005,0 14.58585,0 0,-247.752575 -14.58585,0"
          style="fill:none;stroke:#7f7f7f;stroke-width:7.42626619;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <rect
+         ry="18.94183"
+         transform="translate(0,-847.63782)"
+         y="786.34735"
+         x="525.13226"
+         height="109.91141"
+         width="294.26016"
+         id="rect13292"
+         style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
+      <rect
+         style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+         id="rect14386"
+         width="67.458847"
+         height="32.566402"
+         x="526.29535"
+         y="1003.844"
+         transform="translate(0,-847.63782)"
+         ry="11.630837" />
+      <rect
+         ry="8.359664"
+         transform="translate(0,-847.63782)"
+         y="1014.2391"
+         x="588.30225"
+         height="16.719328"
+         width="32.857113"
+         id="rect15482"
+         style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
+      <rect
+         style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+         id="rect16580"
+         width="72.401962"
+         height="40.998699"
+         x="617.37939"
+         y="991.77704"
+         transform="translate(0,-847.63782)"
+         ry="8.359664" />
+      <rect
+         ry="7.3783121"
+         transform="translate(0,-847.63782)"
+         y="990.90472"
+         x="686.43744"
+         height="14.756624"
+         width="29.0044"
+         id="rect17680"
+         style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
+      <rect
+         style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+         id="rect18782"
+         width="80.391983"
+         height="59.625767"
+         x="706.15411"
+         y="973.33331"
+         transform="translate(0,-847.63782)"
+         ry="7.3783121" />
+      <rect
+         ry="7.3783121"
+         transform="translate(0,-847.63782)"
+         y="973.12775"
+         x="730.41565"
+         height="24.98114"
+         width="52.737965"
+         id="rect19886"
+         style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
+      <rect
+         style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+         id="rect20992"
+         width="315.81097"
+         height="141.86821"
+         x="497.15555"
+         y="926.24957"
+         transform="translate(0,-847.63782)"
+         ry="7.3783121" />
+      <rect
+         ry="7.3783121"
+         transform="translate(0,-847.63782)"
+         y="769.98889"
+         x="389.41794"
+         height="365.97885"
+         width="536.2207"
+         id="rect22100"
+         style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
+      <rect
+         style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+         id="rect23210"
+         width="373.38068"
+         height="216.70882"
+         x="487.28644"
+         y="1087.4447"
+         transform="translate(0,-847.63782)"
+         ry="7.3783121" />
+      <rect
+         ry="7.3783121"
+         transform="translate(0,-847.63782)"
+         y="1214.9205"
+         x="927.6947"
+         height="265.23187"
+         width="493.0434"
+         id="rect24322"
+         style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
     </g>
     <g
        id="g5771"
       </g>
     </g>
     <g
-       id="g6641">
+       id="g6672">
       <rect
-         transform="translate(0,-847.63782)"
          ry="7.6824002"
-         y="1717.6675"
+         y="870.02966"
          x="2073.8433"
          height="146.47212"
          width="291.42902"
          id="rect5216"
-         style="fill:url(#linearGradient6196);stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1.0" />
+         style="fill:url(#linearGradient6670);fill-opacity:1;stroke:none" />
       <g
          transform="matrix(0.63491781,0,0,0.63491781,953.98505,450.85081)"
          id="g6633">
         </a>
       </g>
     </g>
+    <path
+       sodipodi:nodetypes="cccccccc"
+       inkscape:connector-curvature="0"
+       id="rect4048"
+       d="m 395.41572,-563.48609 -15.9557,2.08436 9.39685,71.93232 15.95571,-2.08436 m 319.35106,-41.71833 16.16634,-2.11189 -9.39686,-71.93232 -16.16634,2.11189"
+       style="fill:none;stroke:#7f7f7f;stroke-width:4.24852133;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+    <text
+       transform="matrix(0.99157497,-0.12953409,0.12953409,0.99157497,0,0)"
+       sodipodi:linespacing="125%"
+       id="text3059-0"
+       y="-502.86102"
+       x="476.17603"
+       style="font-size:12.74556351px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#3999b5;fill-opacity:1;stroke:none;font-family:Century Schoolbook L;-inkscape-font-specification:Century Schoolbook L Medium"
+       xml:space="preserve"><tspan
+         y="-502.86102"
+         x="476.17603"
+         id="tspan3061-4"
+         sodipodi:role="line">The Atlassian Platform:</tspan></text>
+    <text
+       transform="matrix(0.99157497,-0.12953409,0.12953409,0.99157497,0,0)"
+       sodipodi:linespacing="125%"
+       id="text4036"
+       y="-482.74905"
+       x="466.44797"
+       style="font-size:12.74556351px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Century Schoolbook L;-inkscape-font-specification:Century Schoolbook L Medium"
+       xml:space="preserve"><tspan
+         id="tspan4040"
+         y="-482.74905"
+         x="466.44797"
+         sodipodi:role="line">A combination of:</tspan><tspan
+         id="tspan4044"
+         y="-466.81711"
+         x="466.44797"
+         sodipodi:role="line">•a framework to host Atlassian plugins</tspan><tspan
+         id="tspan4046"
+         y="-450.88513"
+         x="466.44797"
+         sodipodi:role="line">•a set of libraries &amp; services to support common tasks</tspan></text>
+    <rect
+       style="fill:none;stroke:#ababab;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:0.99999999, 1.99999998;stroke-dashoffset:0"
+       id="rect5456"
+       width="423.18158"
+       height="113.41952"
+       x="411.71518"
+       y="-527.98999"
+       transform="matrix(0.99212937,-0.12521707,0.12521707,0.99212937,0,0)"
+       ry="11.833471" />
+    <rect
+       style="fill:none;stroke:#ababab;stroke-width:1.16624212;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1.16624225, 2.33248453;stroke-dashoffset:0"
+       id="rect5458"
+       width="415.30048"
+       height="147.27344"
+       x="403.65015"
+       y="-483.9603"
+       ry="18.94183" />
+    <rect
+       transform="matrix(0.99199528,-0.12627494,0.12627494,0.99199528,0,0)"
+       style="opacity:0.59670781;fill:url(#linearGradient6690);fill-opacity:1;stroke:none"
+       id="rect5216-1"
+       width="65.97007"
+       height="15.624653"
+       x="482.96735"
+       y="-480.41266"
+       ry="1.9148251" />
+    <rect
+       transform="matrix(0.99199528,-0.12627494,0.12627494,0.99199528,0,0)"
+       style="opacity:0.59670781;fill:url(#linearGradient6687);fill-opacity:1;stroke:none"
+       id="rect5216-1-9"
+       width="116.6298"
+       height="16.546581"
+       x="517.28369"
+       y="-463.78189"
+       ry="1.9148251" />
+    <rect
+       ry="1.9148251"
+       transform="matrix(0.98915153,-0.1468988,0.1468988,0.98915153,0,0)"
+       y="-334.51987"
+       x="541.80835"
+       height="8.0925894"
+       width="48.286217"
+       id="rect5552"
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2.00000003;stroke-dashoffset:0" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect12200"
+       width="346.59894"
+       height="275.06931"
+       x="440.22717"
+       y="506.04419"
+       transform="translate(0,-847.63782)"
+       ry="18.94183" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1.19848955;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1.19848957, 2.39697916;stroke-dashoffset:0"
+       id="rect25458"
+       width="99.790993"
+       height="61.541866"
+       x="1024.6528"
+       y="947.1825"
+       ry="10.124242"
+       transform="matrix(0.93367513,-0.35812115,0.35812115,0.93367513,0,0)" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect27688"
+       width="547.81244"
+       height="301.23868"
+       x="989.78424"
+       y="724.12238"
+       transform="translate(0,-847.63782)"
+       ry="10.124242" />
+    <rect
+       ry="10.124242"
+       transform="translate(0,-847.63782)"
+       y="1028.8503"
+       x="982.80573"
+       height="147.71162"
+       width="557.11707"
+       id="rect28806"
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect29926"
+       width="564.09558"
+       height="466.39658"
+       x="981.64264"
+       y="717.14386"
+       transform="translate(0,-847.63782)"
+       ry="10.124242" />
+    <rect
+       ry="10.124242"
+       transform="translate(0,-847.63782)"
+       y="349.60944"
+       x="1168.899"
+       height="207.02887"
+       width="433.83017"
+       id="rect31048"
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect32172"
+       width="143.0593"
+       height="50.884911"
+       x="1202.3507"
+       y="153.63274"
+       transform="matrix(0.91162377,-0.41102567,0.41102567,0.91162377,0,0)"
+       ry="10.124242" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect32172-3"
+       width="143.0593"
+       height="50.884911"
+       x="1321.2308"
+       y="205.4782"
+       transform="matrix(0.91162377,-0.41102567,0.41102567,0.91162377,0,0)"
+       ry="10.124242" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect32172-1"
+       width="143.0593"
+       height="50.884911"
+       x="1450.5195"
+       y="265.36557"
+       transform="matrix(0.91162377,-0.41102567,0.41102567,0.91162377,0,0)"
+       ry="10.124242" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect32199"
+       width="344.27283"
+       height="162.25018"
+       x="1193.3239"
+       y="534.24896"
+       transform="translate(0,-847.63782)"
+       ry="10.124242" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect36721"
+       width="1055.9929"
+       height="699.06073"
+       x="1952.4354"
+       y="733.80225"
+       transform="translate(0,-847.63782)"
+       ry="10.124242" />
+    <rect
+       ry="10.124242"
+       transform="translate(0,-847.63782)"
+       y="932.82892"
+       x="1921.1833"
+       height="486.87521"
+       width="527.99646"
+       id="rect37855"
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect38991"
+       width="131.17668"
+       height="84.2985"
+       x="2031.7994"
+       y="1076.7532"
+       transform="translate(0,-847.63782)"
+       ry="10.124242" />
+    <rect
+       ry="10.124242"
+       transform="translate(0,-847.63782)"
+       y="1085.7999"
+       x="2146.9387"
+       height="72.784554"
+       width="133.23274"
+       id="rect40129"
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect41269"
+       width="184.63428"
+       height="78.952736"
+       x="2048.2478"
+       y="1168.0424"
+       transform="translate(0,-847.63782)"
+       ry="10.124242" />
+    <rect
+       ry="10.124242"
+       transform="translate(0,-847.63782)"
+       y="1235.4811"
+       x="2054.8274"
+       height="126.65335"
+       width="263.99823"
+       id="rect42411"
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect43555"
+       width="493.72903"
+       height="443.13489"
+       x="2218.5823"
+       y="957.32068"
+       transform="translate(0,-847.63782)"
+       ry="10.124242" />
+    <rect
+       ry="10.124242"
+       transform="translate(0,-847.63782)"
+       y="1234.1345"
+       x="2304.6504"
+       height="158.76093"
+       width="343.10968"
+       id="rect44701"
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect45849"
+       width="152.36397"
+       height="57.572643"
+       x="2397.697"
+       y="1186.4481"
+       transform="translate(0,-847.63782)"
+       ry="10.124242" />
+    <rect
+       ry="10.124242"
+       transform="translate(0,-847.63782)"
+       y="1132.9463"
+       x="2404.6755"
+       height="98.862114"
+       width="147.71162"
+       id="rect46999"
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect48151"
+       width="122.12379"
+       height="65.13269"
+       x="2412.2356"
+       y="1054.4381"
+       transform="translate(0,-847.63782)"
+       ry="10.124242" />
+    <rect
+       ry="10.124242"
+       transform="translate(0,-847.63782)"
+       y="827.55859"
+       x="2443.4229"
+       height="564.18311"
+       width="617.64069"
+       id="rect49305"
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect50461"
+       width="121.7188"
+       height="86.354561"
+       x="2690.1501"
+       y="1174.6217"
+       transform="translate(0,-847.63782)"
+       ry="10.124242" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect50461-3"
+       width="121.7188"
+       height="86.354561"
+       x="2789.6636"
+       y="327.39508"
+       ry="10.124242" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect52795"
+       width="70.111679"
+       height="41.12122"
+       x="2626.001"
+       y="1270.8453"
+       transform="translate(0,-847.63782)"
+       ry="10.124242" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect52795-1"
+       width="70.111679"
+       height="41.12122"
+       x="2674.8323"
+       y="450.34756"
+       ry="10.124242" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1.380741;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1.380741, 2.761482;stroke-dashoffset:0"
+       id="rect52795-3"
+       width="96.806068"
+       height="56.777756"
+       x="2712.8545"
+       y="417.02411"
+       ry="13.978956" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1.69802511;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1.69802517, 3.39605033;stroke-dashoffset:0"
+       id="rect52795-5"
+       width="119.0514"
+       height="69.824867"
+       x="2735.0129"
+       y="464.06091"
+       ry="17.191217" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1.35145319;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1.35145323, 2.70290646;stroke-dashoffset:0"
+       id="rect52795-4"
+       width="94.752655"
+       height="55.573406"
+       x="2808.8579"
+       y="428.9346"
+       ry="13.682439" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
+       id="rect52795-12"
+       width="70.111679"
+       height="41.12122"
+       x="2872.6255"
+       y="472.55298"
+       ry="10.124242" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:1.13179493;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1.13179496, 2.26358992;stroke-dashoffset:0"
+       id="rect52795-2"
+       width="79.352043"
+       height="46.540791"
+       x="2899.4202"
+       y="414.02115"
+       ry="11.458566" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:5.0932188;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:5.09321906, 10.18643812;stroke-dashoffset:0"
+       id="rect52795-12-0"
+       width="357.09415"
+       height="209.43939"
+       x="2629.6208"
+       y="335.76331"
+       ry="51.56498" />
+    <rect
+       ry="424.82614"
+       y="-699.2666"
+       x="-34.888634"
+       height="1725.4989"
+       width="3119.0178"
+       id="rect52795-12-9"
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:43.20541;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:43.20540622, 86.41081244;stroke-dashoffset:0" />
+    <rect
+       style="opacity:0.59670781;fill:none;stroke:#ababab;stroke-width:5.82144976;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:5.82144946, 11.64289892;stroke-dashoffset:0"
+       id="rect52795-12-6"
+       width="390.34207"
+       height="250.30717"
+       x="2028.3394"
+       y="831.83575"
+       ry="61.626831" />
   </g>
+  <script
+     id="sozi-script"
+     ns1:version="12.01-03110225">/*
+ * Sozi - A presentation tool using the SVG standard
+ *
+ * Copyright (C) 2010-2011 Guillaume Savaton
+ *
+ * This program is dual licensed under the terms of the MIT license
+ * or the GNU General Public License (GPL) version 3.
+ * A copy of both licenses is provided in the doc/ folder of the
+ * official release of Sozi.
+ * 
+ * See http://sozi.baierouge.fr/wiki/en:license for details.
+ */
+
+var sozi = sozi || {};
+
+(function () {
+    var exports = sozi.events = sozi.events || {},
+        listeners = {};
+
+    /*
+     * Adds a listener for a given event type.
+     *
+     * The event type is provided as a string by the key parameter.
+     * The function to be executed is provided by the handler parameter.
+     */
+    exports.listen = function (key, handler) {
+        var listenersForKey = listeners[key];
+        if (!listenersForKey) {
+            listenersForKey = listeners[key] = [];
+        }
+        listenersForKey.push(handler);
+    };
+    
+    /*
+     * Fire an event of the given type.
+     *
+     * All event handlers added for the given event type are
+     * executed.
+     * Additional arguments provided to this function are passed
+     * to the event handlers.
+     */
+    exports.fire = function (key) {
+        var listenersForKey = listeners[key],
+            len,
+            i,
+            args = Array.prototype.slice.call(arguments, 1);
+        if (listenersForKey) {
+            len = listenersForKey.length;
+            for (i = 0; i &lt; len; i += 1) {
+                listenersForKey[i].apply(null, args);
+            }
+        }
+    };
+}());
+
+/*
+ * Sozi - A presentation tool using the SVG standard
+ *
+ * Copyright (C) 2010-2011 Guillaume Savaton
+ *
+ * This program is dual licensed under the terms of the MIT license
+ * or the GNU General Public License (GPL) version 3.
+ * A copy of both licenses is provided in the doc/ folder of the
+ * official release of Sozi.
+ * 
+ * See http://sozi.baierouge.fr/wiki/en:license for details.
+ *
+ * @depend events.js
+ */
+
+var sozi = sozi || {};
+
+(function () {
+	var exports = sozi.framelist = sozi.framelist || {},
+        window = this,
+        document = window.document,
+        svgRoot,
+        tocGroup,
+        linksBox,
+        tocHeight = 0,
+        MARGIN = 5,
+        translateXHidden,
+        translateXVisible,
+        translateXStart,
+        translateXEnd,
+        translateX,
+        animator,
+        ANIMATION_TIME_MS = 300,
+        ANIMATION_PROFILE = &quot;decelerate&quot;,
+        SVG_NS = &quot;http://www.w3.org/2000/svg&quot;;
+
+    function makeClickHandler(index) {
+        return function (evt) {
+            sozi.player.previewFrame(index);
+            evt.stopPropagation();
+        };
+    }
+      
+    function defaultEventHandler(evt) {
+	    evt.stopPropagation();
+    }
+    
+	function onMouseOut(evt) {
+        var rel = evt.relatedTarget;
+        while (rel !== tocGroup &amp;&amp; rel !== svgRoot) {
+            rel = rel.parentNode;
+        }
+        if (rel === svgRoot) {
+            exports.hide();
+            sozi.player.restart();
+            evt.stopPropagation();
+        }
+    }
+
+	function onClickArrowUp(evt) {
+        var ty = linksBox.getCTM().f;
+        if (ty &lt;= -window.innerHeight / 2) {
+            ty += window.innerHeight / 2;
+        } else if (ty &lt; 0) {
+            ty = 0;
+        }
+        linksBox.setAttribute(&quot;transform&quot;, &quot;translate(0,&quot; + ty + &quot;)&quot;);
+        evt.stopPropagation();
+	}
+
+	function onClickArrowDown(evt) {
+        var ty = linksBox.getCTM().f;
+        if (ty + tocHeight &gt;= window.innerHeight * 3 / 2) {
+            ty -= window.innerHeight / 2;
+        } else if (ty + tocHeight &gt; window.innerHeight + 2 * MARGIN) {
+            ty = window.innerHeight - tocHeight - 4 * MARGIN;
+        }
+        linksBox.setAttribute(&quot;transform&quot;, &quot;translate(0,&quot; + ty + &quot;)&quot;);
+        evt.stopPropagation();
+    }	
+
+    function onAnimationStep(progress) {
+        var profileProgress = sozi.animation.profiles[ANIMATION_PROFILE](progress),
+            remaining = 1 - profileProgress;
+        translateX = translateXEnd * profileProgress + translateXStart * remaining;
+        tocGroup.setAttribute(&quot;transform&quot;, &quot;translate(&quot; + translateX + &quot;,0)&quot;);
+    }
+    
+    function onAnimationDone() {
+        // Empty
+    }
+    
+    /*
+     * Adds a table of contents to the document.
+     *
+     * The table of contents is a rectangular region with the list of frame titles.
+     * Clicking on a title moves the presentation to the corresponding frame.
+     *
+     * The table of contents is hidden by default.
+     */
+    function onDisplayReady() {
+        var tocBackground = document.createElementNS(SVG_NS, &quot;rect&quot;),
+            tocUp = document.createElementNS(SVG_NS, &quot;path&quot;),
+            tocDown = document.createElementNS(SVG_NS, &quot;path&quot;),
+            tocWidth = 0,
+            textWidth,
+            frameCount = sozi.document.frames.length,
+            frameIndex = sozi.location.getFrameIndex(),
+            i,
+            text;
+
+		svgRoot = document.documentElement;
+
+        tocGroup = document.createElementNS(SVG_NS, &quot;g&quot;);
+        tocGroup.setAttribute(&quot;id&quot;, &quot;sozi-toc&quot;);
+        svgRoot.appendChild(tocGroup);
+
+        linksBox = document.createElementNS(SVG_NS, &quot;g&quot;);
+        tocGroup.appendChild(linksBox);
+    
+        tocBackground.setAttribute(&quot;id&quot;, &quot;sozi-toc-background&quot;);
+        tocBackground.setAttribute(&quot;x&quot;, MARGIN);
+        tocBackground.setAttribute(&quot;y&quot;, MARGIN);
+        tocBackground.setAttribute(&quot;rx&quot;, MARGIN);
+        tocBackground.setAttribute(&quot;ry&quot;, MARGIN);
+        tocBackground.addEventListener(&quot;click&quot;, defaultEventHandler, false);
+        tocBackground.addEventListener(&quot;mousedown&quot;, defaultEventHandler, false);
+        tocBackground.addEventListener(&quot;mouseout&quot;, onMouseOut, false);
+        linksBox.appendChild(tocBackground);
+
+        for (i = 0; i &lt; frameCount; i += 1) {
+            text = document.createElementNS(SVG_NS, &quot;text&quot;);
+            text.appendChild(document.createTextNode(sozi.document.frames[i].title));
+            linksBox.appendChild(text);
+
+            if (i === frameIndex) {
+                text.setAttribute(&quot;class&quot;, &quot;sozi-toc-current&quot;);
+            }
+                     
+            textWidth = text.getBBox().width;
+            tocHeight += text.getBBox().height;
+            if (textWidth &gt; tocWidth) {
+                tocWidth = textWidth;
+            }
+
+            text.setAttribute(&quot;x&quot;, 2 * MARGIN);
+            text.setAttribute(&quot;y&quot;, tocHeight + MARGIN);
+            text.addEventListener(&quot;click&quot;, makeClickHandler(i), false);
+            text.addEventListener(&quot;mousedown&quot;, defaultEventHandler, false);
+        }
+
+        tocUp.setAttribute(&quot;class&quot;, &quot;sozi-toc-arrow&quot;);
+        tocUp.setAttribute(&quot;d&quot;, &quot;M&quot; + (tocWidth + 3 * MARGIN) + &quot;,&quot; + (5 * MARGIN) + 
+                           &quot; l&quot; + (4 * MARGIN) + &quot;,0&quot; +
+                           &quot; l-&quot; + (2 * MARGIN) + &quot;,-&quot; + (3 * MARGIN) +
+                           &quot; z&quot;);
+        tocUp.addEventListener(&quot;click&quot;, onClickArrowUp, false);
+        tocUp.addEventListener(&quot;mousedown&quot;, defaultEventHandler, false);
+        tocGroup.appendChild(tocUp);
+      
+        tocDown.setAttribute(&quot;class&quot;, &quot;sozi-toc-arrow&quot;);
+        tocDown.setAttribute(&quot;d&quot;, &quot;M&quot; + (tocWidth + 3 * MARGIN) + &quot;,&quot; + (7 * MARGIN) + 
+                             &quot; l&quot; + (4 * MARGIN) + &quot;,0&quot; +
+                             &quot; l-&quot; + (2 * MARGIN) + &quot;,&quot; + (3 * MARGIN) +
+                             &quot; z&quot;);
+        tocDown.addEventListener(&quot;click&quot;, onClickArrowDown, false);
+        tocDown.addEventListener(&quot;mousedown&quot;, defaultEventHandler, false);      
+        tocGroup.appendChild(tocDown);
+
+        tocBackground.setAttribute(&quot;width&quot;, tocWidth + 7 * MARGIN);
+        tocBackground.setAttribute(&quot;height&quot;, tocHeight + 2 * MARGIN);
+        
+        translateXHidden = -tocWidth - 9 * MARGIN;
+        translateXVisible = 0;
+        translateX = translateXEnd = translateXHidden;
+        
+        tocGroup.setAttribute(&quot;transform&quot;, &quot;translate(&quot; + translateXHidden + &quot;,0)&quot;);
+        animator = new sozi.animation.Animator(onAnimationStep, onAnimationDone);
+    }
+
+    function onFrameChange(index) {
+        var current = document.getElementsByClassName(&quot;sozi-toc-current&quot;),
+            textElements = linksBox.getElementsByTagName(&quot;text&quot;),
+            i;
+        for (i = 0; i &lt; current.length; i += 1) {
+            current[i].removeAttribute(&quot;class&quot;);
+        }
+        textElements[index].setAttribute(&quot;class&quot;, &quot;sozi-toc-current&quot;);
+    }
+    
+    /*
+     * Makes the table of contents visible.
+     */
+    exports.show = function () {
+        translateXStart = translateX;
+        translateXEnd = translateXVisible;
+        animator.start(ANIMATION_TIME_MS); // FIXME depends on current elapsed time
+    };
+
+    /*
+     * Makes the table of contents invisible.
+     */
+    exports.hide = function () {
+        translateXStart = translateX;
+        translateXEnd = translateXHidden;
+        animator.start(ANIMATION_TIME_MS); // FIXME depends on current elapsed time
+    };
+
+    /*
+     * Returns true if the table of contents is visible, false otherwise.
+     */
+    exports.isVisible = function () {
+        return translateXEnd === translateXVisible;
+    };
+
+	sozi.events.listen(&quot;displayready&quot;, onDisplayReady);
+	sozi.events.listen(&quot;cleanup&quot;, exports.hide);
+	sozi.events.listen(&quot;framechange&quot;, onFrameChange);
+}());
+
+/*
+ * Sozi - A presentation tool using the SVG standard
+ *
+ * Copyright (C) 2010-2011 Guillaume Savaton
+ *
+ * This program is dual licensed under the terms of the MIT license
+ * or the GNU General Public License (GPL) version 3.
+ * A copy of both licenses is provided in the doc/ folder of the
+ * official release of Sozi.
+ * 
+ * See http://sozi.baierouge.fr/wiki/en:license for details.
+ */
+
+var sozi = sozi || {};
+
+(function () {
+    var player = sozi.player = sozi.player || {},
+        display = sozi.display = sozi.display || {},
+        window = this,
+        document = window.document,
+        DRAG_BUTTON = 0, // Left button
+        TOC_BUTTON = 1, // Middle button
+        SCALE_FACTOR = 1.05,
+        ROTATE_STEP = 5,
+        dragButtonIsDown = false,
+        dragged = false,
+        dragClientX = 0,
+        dragClientY = 0;
+    
+    /*
+     * Zooms the display in the given direction.
+     *
+     * Only the sign of direction is used:
+     *    - zoom in when direction &gt; 0
+     *    - zoom out when direction &lt;= 0
+     *
+     * The scaling is centered around point (x, y).
+     */
+    function zoom(direction, x, y) {
+        player.stop();
+        display.zoom(direction &gt; 0 ? SCALE_FACTOR : 1 / SCALE_FACTOR, x, y);
+    }
+    
+    /*
+     * Rotate the display in the given direction.
+     *
+     * Only the sign of direction is used:
+     *    - rotate anticlockwise when direction &gt; 0
+     *    - rotate clockwise when direction &lt;= 0
+     */
+    function rotate(direction) {
+        player.stop();
+        display.rotate(direction &gt; 0 ? ROTATE_STEP : -ROTATE_STEP);
+    }
+    
+    function toggleFrameList() {
+        if (sozi.framelist.isVisible()) {
+            sozi.framelist.hide();
+            player.restart();
+        } else {
+            player.stop();
+            sozi.framelist.show();
+        }
+    }
+
+    /*
+     * Event handler: mouse down.
+     *
+     * When the left button is pressed, we register the current coordinates
+     * in case the mouse will be dragged. Flag &quot;dragButtonIsDown&quot; is set until
+     * the button is released (onMouseUp). This flag is used by onMouseMove.
+     *
+     * When the middle button is pressed, the table of contents is shown or hidden.
+     */
+    function onMouseDown(evt) {
+        if (evt.button === DRAG_BUTTON) {
+            dragButtonIsDown = true;
+            dragged = false;
+            dragClientX = evt.clientX;
+            dragClientY = evt.clientY;
+        } else if (evt.button === TOC_BUTTON) {
+            toggleFrameList();
+        }
+        evt.stopPropagation();
+    }
+
+    /*
+     * Event handler: mouse move.
+     *
+     * If the left mouse button is down, then the mouse move is a drag action.
+     * This method computes the displacement since the button was pressed or
+     * since the last move, and updates the reference coordinates for the next move.
+     */
+    function onMouseMove(evt) {
+        if (dragButtonIsDown) {
+            player.stop();
+            dragged = true;
+            sozi.events.fire(&quot;cleanup&quot;);
+            display.drag(evt.clientX - dragClientX, evt.clientY - dragClientY);
+            dragClientX = evt.clientX;
+            dragClientY = evt.clientY;
+        }
+        evt.stopPropagation();
+    }
+
+    /*
+     * Event handler: mouse up.
+     *
+     * Releasing the left button resets the &quot;dragButtonIsDown&quot; flag.
+     */
+    function onMouseUp(evt) {
+        if (evt.button === DRAG_BUTTON) {
+            dragButtonIsDown = false;
+        }
+        evt.stopPropagation();
+    }
+
+    /*
+     * Event handler: context menu (i.e. right click).
+     *
+     * Right click goes one frame back.
+     *
+     * There is no &quot;click&quot; for the right mouse button and the menu can't
+     * be prevented in &quot;onMouseDown&quot;.
+     */
+    function onContextMenu(evt) {
+        player.moveToPrevious();
+        evt.stopPropagation();
+        evt.preventDefault();
+    }
+
+    /*
+     * Event handler: mouse click.
+     *
+     * Left-click moves the presentation to the next frame.
+     *
+     * No &quot;click&quot; event is generated for the middle button in Firefox.
+     * See &quot;onMouseDown&quot; for middle click handling.
+     *
+     * Dragging the mouse produces a &quot;click&quot; event when the button is released.
+     * If flag &quot;dragged&quot; was set by &quot;onMouseMove&quot;, then the click event is the result
+     * of a drag action.
+     */
+    function onClick(evt) {
+        if (!dragged &amp;&amp; evt.button !== TOC_BUTTON) {
+            player.moveToNext();
+        }
+        evt.stopPropagation();
+    }
+
+    /*
+     * Event handler: mouse wheel.
+     *
+     * Rolling the mouse wheel stops the presentation and zooms the current display.
+     */
+    function onWheel(evt) {
+        var delta = 0;
+        if (!evt) {
+            evt = window.event;
+        }
+        if (evt.wheelDelta) { // IE and Opera
+            delta = evt.wheelDelta; 
+            if (window.opera) { // Opera
+                delta = -delta;
+            }
+        } else if (evt.detail) { // Mozilla
+            delta = -evt.detail;
+        }
+
+        if (delta !== 0) {
+            if (evt.shiftKey) {
+                rotate(delta);
+            } else {
+                zoom(delta, evt.clientX, evt.clientY);
+            }
+        }
+        evt.stopPropagation();
+        evt.preventDefault();
+    }
+
+    /*
+     * Event handler: key press.
+     *
+     * Keyboard handling is split into two methods: onKeyPress and onKeyDown
+     * in order to get the same behavior in Mozilla and Webkit.
+     *
+     * This method handles character keys &quot;+&quot;, &quot;-&quot;, &quot;=&quot;, &quot;F&quot; and &quot;T&quot;.
+     */
+    function onKeyPress(evt) {
+        switch (evt.charCode) {
+        case 43: // +
+            zoom(1, window.innerWidth / 2, window.innerHeight / 2);
+            break;
+        case 45: // -
+            zoom(-1, window.innerWidth / 2, window.innerHeight / 2);
+            break;
+        case 61: // =
+            player.moveToCurrent();
+            break;
+        case 70: // F
+        case 102: // f
+            player.showAll();
+            break;
+        case 84: // T
+        case 116: // t
+            toggleFrameList();
+            break;
+        case 82: // R
+            rotate(-1);
+            break;
+        case 114: // r
+            rotate(1);
+            break;
+        }
+        evt.stopPropagation();
+    }
+
+    /*
+     * Event handler: key down.
+     *
+     * Keyboard handling is split into two methods: onKeyPress and onKeyDown
+     * in order to get the same behavior in Mozilla and Webkit.
+     *
+     * This method handles navigation keys (arrows, page up/down, home, end)
+     * and the space and enter keys.
+     */
+    function onKeyDown(evt) {
+        switch (evt.keyCode) {
+        case 36: // Home
+            player.moveToFirst();
+            break;
+        case 35: // End
+            player.moveToLast();
+            break;
+        case 38: // Arrow up
+            player.jumpToPrevious();
+            break;
+        case 33: // Page up
+        case 37: // Arrow left
+            player.moveToPrevious();
+            break;
+        case 40: // Arrow down
+            player.jumpToNext();
+            break;
+        case 34: // Page down
+        case 39: // Arrow right
+        case 13: // Enter
+        case 32: // Space
+            player.moveToNext();
+            break;
+        }
+        evt.stopPropagation();
+    }
+
+    function onLoad() {
+        var svgRoot = document.documentElement;
+
+        // TODO also use shift-click as an alternative for middle-click
+        svgRoot.addEventListener(&quot;click&quot;, onClick, false);
+        svgRoot.addEventListener(&quot;mousedown&quot;, onMouseDown, false);
+        svgRoot.addEventListener(&quot;mouseup&quot;, onMouseUp, false);
+        svgRoot.addEventListener(&quot;mousemove&quot;, onMouseMove, false);
+        svgRoot.addEventListener(&quot;keypress&quot;, onKeyPress, false);
+        svgRoot.addEventListener(&quot;keydown&quot;, onKeyDown, false);
+        svgRoot.addEventListener(&quot;contextmenu&quot;, onContextMenu, false);
+        svgRoot.addEventListener(&quot;DOMMouseScroll&quot;, onWheel, false); // Mozilla
+        window.onmousewheel = onWheel;
+    }
+
+    window.addEventListener(&quot;load&quot;, onLoad, false);
+}());
+
+/*
+ * Sozi - A presentation tool using the SVG standard
+ *
+ * Copyright (C) 2010-2011 Guillaume Savaton
+ *
+ * This program is dual licensed under the terms of the MIT license
+ * or the GNU General Public License (GPL) version 3.
+ * A copy of both licenses is provided in the doc/ folder of the
+ * official release of Sozi.
+ * 
+ * See http://sozi.baierouge.fr/wiki/en:license for details.
+ */
+
+var sozi = sozi || {};
+
+(function () {
+    var exports = sozi.animation = sozi.animation || {},
+        window = this,
+        TIME_STEP_MS = 40,
+        animators = [],
+        timer,
+        requestAnimationFrame = window.mozRequestAnimationFrame ||
+            window.webkitRequestAnimationFrame ||
+            window.msRequestAnimationFrame ||
+            window.oRequestAnimationFrame;
+
+    function start() {
+        if (requestAnimationFrame) {
+            requestAnimationFrame(loop);
+        }
+        else {
+            timer = window.setInterval(function() {
+                loop(Date.now());
+            }, TIME_STEP_MS);
+        }
+    }
+    
+    function loop(timestamp) {
+        var i;
+        if (animators.length &gt; 0) {
+            if (requestAnimationFrame) {
+                requestAnimationFrame(loop);
+            }
+            for (i = 0; i &lt; animators.length; i += 1) {
+                animators[i].step(timestamp)
+            }
+        }
+        else {
+            if (!requestAnimationFrame) {
+                window.clearInterval(timer);
+            }
+        }
+    }
+    
+    function addAnimator(animator) {
+        animators.push(animator);
+        if (animators.length === 1) {
+            start();
+        }
+    }
+    
+    function removeAnimator(animator) {
+        animators.splice(animators.indexOf(animator), 1);
+    }
+    
+    exports.Animator = function (onStep, onDone) {
+        this.onStep = onStep;
+        this.onDone = onDone;
+
+        this.durationMs = 0;
+        this.data = {};
+        this.initialTime = 0;
+        this.started = false;
+    };
+
+    exports.Animator.prototype.start = function (durationMs, data) {
+        this.durationMs = durationMs;
+        this.data = data;
+
+        this.initialTime = Date.now();
+        this.onStep(0, this.data);
+
+        if (!this.started) {
+            this.started = true;
+            addAnimator(this);
+        }
+    };
+
+    exports.Animator.prototype.stop = function () {
+        if (this.started) {
+            removeAnimator(this);
+            this.started = false;
+        }
+    };
+
+    exports.Animator.prototype.step = function (timestamp) {
+        var elapsedTime = timestamp - this.initialTime;
+        if (elapsedTime &gt;= this.durationMs) {
+            this.stop();
+            this.onStep(1, this.data);
+            this.onDone();
+        } else {
+            this.onStep(elapsedTime / this.durationMs, this.data);
+        }
+    };
+
+    exports.profiles = {
+        &quot;linear&quot;: function (x) {
+            return x;
+        },
+
+        &quot;accelerate&quot;: function (x) {
+            return Math.pow(x, 3);
+        },
+
+        &quot;strong-accelerate&quot;: function (x) {
+            return Math.pow(x, 5);
+        },
+
+        &quot;decelerate&quot;: function (x) {
+            return 1 - Math.pow(1 - x, 3);
+        },
+
+        &quot;strong-decelerate&quot;: function (x) {
+            return 1 - Math.pow(1 - x, 5);
+        },
+
+        &quot;accelerate-decelerate&quot;: function (x) {
+            var xs = x &lt;= 0.5 ? x : 1 - x,
+                y = Math.pow(2 * xs, 3) / 2;
+            return x &lt;= 0.5 ? y : 1 - y;
+        },
+
+        &quot;strong-accelerate-decelerate&quot;: function (x) {
+            var xs = x &lt;= 0.5 ? x : 1 - x,
+                y = Math.pow(2 * xs, 5) / 2;
+            return x &lt;= 0.5 ? y : 1 - y;
+        },
+
+        &quot;decelerate-accelerate&quot;: function (x) {
+            var xs = x &lt;= 0.5 ? x : 1 - x,
+                y = (1 - Math.pow(1 - 2 * xs, 2)) / 2;
+            return x &lt;= 0.5 ? y : 1 - y;
+        },
+
+        &quot;strong-decelerate-accelerate&quot;: function (x) {
+            var xs = x &lt;= 0.5 ? x : 1 - x,
+                y = (1 - Math.pow(1 - 2 * xs, 3)) / 2;
+            return x &lt;= 0.5 ? y : 1 - y;
+        }
+    };
+}());
+
+
+/*
+ * Sozi - A presentation tool using the SVG standard
+ *
+ * Copyright (C) 2010-2011 Guillaume Savaton
+ *
+ * This program is dual licensed under the terms of the MIT license
+ * or the GNU General Public License (GPL) version 3.
+ * A copy of both licenses is provided in the doc/ folder of the
+ * official release of Sozi.
+ * 
+ * See http://sozi.baierouge.fr/wiki/en:license for details.
+ *
+ * @depend events.js
+ * @depend animation.js
+ */
+
+var sozi = sozi || {};
+
+(function () {
+    var exports = sozi.player = sozi.player || {},
+        display = sozi.display = sozi.display || {},
+        window = this,
+        animator,
+        nextFrameTimeout,
+        DEFAULT_DURATION_MS = 500,
+        DEFAULT_ZOOM_PERCENT = -10,
+        DEFAULT_PROFILE = &quot;linear&quot;,
+        sourceFrameIndex = 0,
+        currentFrameIndex = 0,
+        playing = false,
+        waiting = false;
+
+    /*
+     * Event handler: animation step.
+     *
+     * This method is called periodically by animator after the animation
+     * has been started, and until the animation time is elapsed.
+     *
+     * Parameter data provides the following information:
+     *    - initialState and finalState contain the geometrical properties of the display
+     *      at the start and end of the animation.
+     *    - profile is a reference to the speed profile function to use.
+     *    - zoomWidth and zoomHeight are the parameters of the zooming polynomial if the current
+     *      animation has a non-zero zooming effect.
+     *
+     * Parameter progress is a float number between 0 (start of the animation)
+     * and 1 (end of the animation).
+     */
+    function onAnimationStep(progress, data) {
+        var remaining = 1 - progress,
+            profileProgress = data.profile(progress),
+            profileRemaining = 1 - profileProgress,
+            attr,
+            ps;
+
+        for (attr in data.initialState) {
+            if (data.initialState.hasOwnProperty(attr)) {
+                if (typeof data.initialState[attr] === &quot;number&quot; &amp;&amp; typeof data.finalState[attr] === &quot;number&quot;) {
+                    display.geometry[attr] = data.finalState[attr] * profileProgress + data.initialState[attr] * profileRemaining;
+                }
+            }
+        }
+
+        if (data.zoomWidth &amp;&amp; data.zoomWidth.k !== 0) {
+            ps = progress - data.zoomWidth.ts;
+            display.geometry.width = data.zoomWidth.k * ps * ps + data.zoomWidth.ss;
+        }
+
+        if (data.zoomHeight &amp;&amp; data.zoomHeight.k !== 0) {
+            ps = progress - data.zoomHeight.ts;
+            display.geometry.height = data.zoomHeight.k * ps * ps + data.zoomHeight.ss;
+        }
+
+        display.clip = data.finalState.clip;
+
+        display.update();
+    }
+
+    /*
+     * Starts waiting before moving to the next frame.
+     *
+     * It the current frame has a timeout set, this method
+     * will register a timer to move to the next frame automatically
+     * after the specified time.
+     *
+     * If the current frame is the last, the presentation will
+     * move to the first frame.
+     */
+    function waitTimeout() {
+        var index;
+        if (sozi.document.frames[currentFrameIndex].timeoutEnable) {
+            waiting = true;
+            index = (currentFrameIndex + 1) % sozi.document.frames.length;
+            nextFrameTimeout = window.setTimeout(function () {
+                    exports.moveToFrame(index);
+                },
+                sozi.document.frames[currentFrameIndex].timeoutMs
+            );
+        }
+    }
+
+    /*
+     * Event handler: animation done.
+     *
+     * This method is called by animator when the current animation is finished.
+     *
+     * If the animation was a transition in the normal course of the presentation,
+     * then we call the waitTimeout method to process the timeout property of the current frame.
+     */
+    function onAnimationDone() {
+        sourceFrameIndex = currentFrameIndex;
+        if (playing) {
+            waitTimeout();
+        }
+    }
+
+    /*
+     * Starts the presentation from the given frame index (0-based).
+     *
+     * This method sets the &quot;playing&quot; flag, shows the desired frame
+     * and calls waitTimeout.
+     */
+    exports.startFromIndex = function (index) {
+        playing = true;
+        waiting = false;
+        sourceFrameIndex = index;
+        currentFrameIndex = index;
+        display.showFrame(sozi.document.frames[index]);
+        waitTimeout();
+    };
+
+    exports.restart = function () {
+        exports.startFromIndex(currentFrameIndex);
+    };
+
+    /*
+     * Stops the presentation.
+     *
+     * This method clears the &quot;playing&quot;.
+     * If the presentation was in &quot;waiting&quot; mode due to a timeout
+     * in the current frame, then it stops waiting.
+     * The current animation is stopped in its current state.
+     */
+    exports.stop = function () {
+        animator.stop();
+        if (waiting) {
+            window.clearTimeout(nextFrameTimeout);
+            waiting = false;
+        }
+        playing = false;
+        sourceFrameIndex = currentFrameIndex;
+    };
+
+    function getZoomData(zoomPercent, s0, s1) {
+        var result = {
+                ss: ((zoomPercent &lt; 0) ? Math.max(s0, s1) : Math.min(s0, s1)) * (100 - zoomPercent) / 100,
+                ts: 0.5,
+                k: 0
+            },
+            a,
+            b,
+            c,
+            d,
+            u,
+            v;
+
+        if (zoomPercent !== 0) {
+            a = s0 - s1;
+            b = s0 - result.ss;
+            c = s1 - result.ss;
+
+            if (a !== 0) {
+                d = Math.sqrt(b * c);
+
+                u = (b - d) / a;
+                v = (b + d) / a;
+
+                result.ts = (u &gt; 0 &amp;&amp; u &lt;= 1) ? u : v;
+            }
+
+            result.k = b / result.ts / result.ts;
+        }
+
+        return result;
+    }
+
+    /*
+     * Jump to a frame with the given index (0-based).
+     *
+     * This method does not animate the transition from the current
+     * state of the display to the desired frame.
+     *
+     * The presentation is stopped: if a timeout has been set for the
+     * target frame, it will be ignored.
+     *
+     * The URL hash is set to the given frame index (1-based).
+     */
+    exports.jumpToFrame = function (index) {
+        exports.stop();
+        sozi.events.fire(&quot;cleanup&quot;);
+
+        sourceFrameIndex = index;
+        currentFrameIndex = index;
+        display.showFrame(sozi.document.frames[index]);
+
+        sozi.events.fire(&quot;framechange&quot;, index);
+    };
+
+    exports.previewFrame = function (index) {
+        var finalState = sozi.document.frames[index].geometry,
+            zw,
+            zh;
+
+        if (DEFAULT_ZOOM_PERCENT !== 0) {
+            zw = getZoomData(DEFAULT_ZOOM_PERCENT, display.geometry.width, finalState.width);
+            zh = getZoomData(DEFAULT_ZOOM_PERCENT, display.geometry.height, finalState.height);
+        }
+
+        currentFrameIndex = index;
+        animator.start(DEFAULT_DURATION_MS,  {
+            initialState: display.getCurrentGeometry(),
+            finalState: finalState,
+            profile: sozi.animation.profiles[DEFAULT_PROFILE],
+            zoomWidth: zw,
+            zoomHeight: zh
+        });
+
+        sozi.events.fire(&quot;framechange&quot;, index);
+    };
+
+    /*
+     * Moves to a frame with the given index (0-based).
+     *
+     * This method animates the transition from the current
+     * state of the display to the desired frame.
+     *
+     * If the given frame index corresponds to the next frame in the list,
+     * the transition properties of the next frame are used.
+     * Otherwise, default transition properties are used.
+     *
+     * The URL hash is set to the given frame index (1-based).
+     */
+    exports.moveToFrame = function (index) {
+        var durationMs = DEFAULT_DURATION_MS,
+            zoomPercent = DEFAULT_ZOOM_PERCENT,
+            profile = sozi.animation.profiles[DEFAULT_PROFILE],
+            zw,
+            zh;
+
+        if (waiting) {
+            window.clearTimeout(nextFrameTimeout);
+            waiting = false;
+        }
+