Upgrade graphs to Flotr2
Upgrade graphs to Flotr2

file:b/.gitmodules (new)
--- /dev/null
+++ b/.gitmodules
@@ -1,1 +1,7 @@
+[submodule "js/flotr2"]
+	path = js/flotr2
+	url = https://github.com/HumbleSoftware/Flotr2.git
+[submodule "js/FlashCanvas"]
+	path = js/FlashCanvas
+	url = https://github.com/timcameronryan/FlashCanvas
 

--- a/geo/route.kml.php
+++ b/geo/route.kml.php
@@ -1,30 +1,105 @@
 <?php
 header('Content-Type: application/vnd.google-earth.kml+xml');
 include ('../include/common.inc.php');
+header('Content-Disposition: attachment; filename="route.' . urlencode($routeid) . '.kml"');
+$debugOkay = Array(); // disable debugging output even on dev server
 echo '<?xml version="1.0" encoding="UTF-8"?>
 <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom"><Document>';
 echo '
-    <Style id="yellowLineGreenPoly">
+     <Style id="ylw-pushpin">
+    <IconStyle>
+      <Icon>
+        <href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
+        
+      </Icon>
+    </IconStyle>
+    
+  </Style>
+          <Style id="blue-pushpin">
+    <IconStyle>
+      <Icon>
+        <href>http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png</href>
+        
+      </Icon>
+    </IconStyle>
+    
+  </Style>
+          <Style id="grn-pushpin">
+    <IconStyle>
+      <Icon>
+        <href>http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png</href>
+        
+      </Icon>
+    </IconStyle>
+  </Style>
+    <Style id="yellowLineYellowPoly">
       <LineStyle>
-        <color>7f00ff00</color>
+        <color>7f00ebff</color>
         <width>4</width>
       </LineStyle>
       <PolyStyle>
-        <color>7f00ffff</color>
+        <color>7f00ebff</color>
       </PolyStyle>
-	</Style>';
+	</Style>
+            <Style id="blueLineBluePoly">
+      <LineStyle>
+        <color>7fff0000</color>
+        <width>4</width>
+      </LineStyle>
+      <PolyStyle>
+        <color>7fff0000</color>
+      </PolyStyle>
+	</Style>
+        ';
 $route = getRoute($routeid);
- echo "\n<Placemark>\n";
- $link = curPageURL()."/../trip.php?routeid=".htmlspecialchars ($route["route_id"]);
- echo "<name>".$route['route_short_name']."</name>";
-  echo '<atom:link href="'.$link.'"/>';
- echo '<description><![CDATA[ <a href="'.$link.'">'.$route['route_short_name']." ".$route['route_long_name']."</a>]]> </description>";
-echo "<styleUrl>#yellowLineGreenPoly</styleUrl>";
+echo "\n<Placemark>\n";
+$_REQUEST['time'] = "12:00";
+$trip = getRouteNextTrip($routeid, 0);
+$link = curPageURL() . "/../trip.php?routeid=" . htmlspecialchars($route["route_id"]. "&directionid=0&tripid=".$trip['trip_id']) ;
+echo "<name>" . $route['route_short_name'] . " Direction 0 </name>";
+echo '<atom:link rel="related" href="' . $link . '"/>';
+echo '<description><![CDATA[ <a href="' . $link . '">' . $route['route_short_name'] . " Direction 0</a>]]> </description>";
+echo "<styleUrl>#yellowLineYellowPoly</styleUrl>";
 
-	$trip = getRouteNextTrip($routeid);
-	echo getTripShape($trip['trip_id']);
+echo getTripShape($trip['trip_id']);
+    echo "</Placemark>\n";
+$stops = Array();
+foreach (getTripStops($trip['trip_id']) as $stop) {
+    $stop['style'] = "#ylw-pushpin";
+    $stops[$stop['stop_id']] = $stop;
+}
 
-echo "</Placemark>\n</Document></kml>\n";
+
+echo "\n<Placemark>\n";
+$trip = getRouteNextTrip($routeid, 1);
+$link = curPageURL() . "/../trip.php?routeid=" . htmlspecialchars($route["route_id"]. "&directionid=1&tripid=".$trip['trip_id']) ;
+echo "<name>" . $route['route_short_name'] . " Direction 1 </name>";
+echo '<atom:link rel="related" href="' . $link . '"/>';
+echo '<description><![CDATA[ <a href="' . $link . '">' . $route['route_short_name'] . " Direction 1</a>]]> </description>";
+echo "<styleUrl>#blueLineBluePoly</styleUrl>";
+
+echo getTripShape($trip['trip_id']);
+    echo "</Placemark>\n";
+foreach (getTripStops($trip['trip_id']) as $stop) {
+    if (isset($stops[$stop['stop_id']])) {
+        $stop['style'] = "#grn-pushpin";
+    } else {
+        $stop['style'] = "#blue-pushpin";
+    }
+    $stops[$stop['stop_id']] = $stop;
+}
+foreach ($stops as $stop) {
+    echo "\n<Placemark>\n";
+    $link = curPageURL() . '/../stop.php?stopid=' . htmlspecialchars($stop['stop_id']);
+    echo "<name>" . htmlspecialchars($stop['stop_name']) . "</name>";
+    echo '<atom:link rel="related" href="' . $link . '"/>';
+    echo '<description><![CDATA[ <a href="' . $link . '">' . htmlspecialchars($stop['stop_name']) . "</a>]]> </description>";
+    echo "<styleUrl>" . $stop['style'] . "</styleUrl>";
+    echo $stop['positionkml'];
+    echo "</Placemark>\n";
+}
+
+echo "</Document></kml>\n";
 ?>
 
 

--- a/geo/stops.kml.php
+++ b/geo/stops.kml.php
@@ -1,11 +1,13 @@
 <?php

+header('Content-type: application/vnd.google-earth.kml+xml');

 include ('../include/common.inc.php');

-header('Content-type: application/vnd.google-earth.kml+xml');

+header('Content-Disposition: attachment; filename="stops.kml"');

+$debugOkay = Array(); // disable debugging output even on dev server

 //http://wiki.openstreetmap.org/wiki/OpenLayers_Dynamic_KML

 // Creates the KML/XML Document.

 $dom = new DOMDocument('1.0', 'UTF-8');

 // Creates the root KML element and appends it to the root document.

-$node = $dom->createElementNS('http://earth.google.com/kml/2.1', 'kml');

+$node = $dom->createElementNS('http://www.opengis.net/kml/2.2', 'kml');

 $parNode = $dom->appendChild($node);

 // Creates a KML Document element and append it to the KML element.

 $dnode = $dom->createElement('Document');

@@ -13,7 +15,7 @@
 if ($suburb != "") $result_stops = getStopsBySuburb($suburb);

 else $result_stops = getStops();

 foreach ($result_stops as $stop) {

-	$description = 'http://bus.lambdacomplex.org/' . 'stop.php?stopid=' . $stop['stop_id'] . " <br>";

+	$description = '<a href="'.curPageURL() . '/../stop.php?stopid=' . $stop['stop_id'] . '">View stop page</a><br>';

 	// Creates a Placemark and append it to the Document.

 	$node = $dom->createElement('Placemark');

 	$placeNode = $docNode->appendChild($node);


file:b/geo/trip.kml.php (new)
--- /dev/null
+++ b/geo/trip.kml.php
@@ -1,1 +1,70 @@
+<?php
+header('Content-Type: application/vnd.google-earth.kml+xml');
+include ('../include/common.inc.php');
+header('Content-Disposition: attachment; filename="trip.' . urlencode($tripid) . '.kml"');
+$debugOkay = Array(); // disable debugging output even on dev server
+echo '<?xml version="1.0" encoding="UTF-8"?>
+<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom"><Document>';
+echo '
+      <Style id="ylw-pushpin">
+    <IconStyle>
+      <Icon>
+        <href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
+        
+      </Icon>
+    </IconStyle>
+    
+  </Style>
+          <Style id="blue-pushpin">
+    <IconStyle>
+      <Icon>
+        <href>http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png</href>
+        
+      </Icon>
+    </IconStyle>
+    
+  </Style>
+          <Style id="grn-pushpin">
+    <IconStyle>
+      <Icon>
+        <href>http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png</href>
+        
+      </Icon>
+    </IconStyle>
+  </Style>
+    <Style id="yellowLineGreenPoly">
+      <LineStyle>
+        <color>7f00ff00</color>
+        <width>4</width>
+      </LineStyle>
+      <PolyStyle>
+        <color>7f00ffff</color>
+      </PolyStyle>
+	</Style>';
+$trip = getTrip($tripid);
+echo "\n<Placemark>\n";
+$link = curPageURL() . "/../trip.php?tripid=" . htmlspecialchars($$tripid);
+echo "<name>" . $tripid . "</name>";
+echo '<atom:link rel="related" href="' . $link . '"/>';
+echo '<description><![CDATA[ <a href="' . $link . '">' . $tripid . "</a>]]> </description>";
+echo "<styleUrl>#yellowLineGreenPoly</styleUrl>";
 
+
+echo getTripShape($tripid);
+
+echo "</Placemark>\n";
+foreach (getTripStopTimes($tripid) as $stop) {
+    echo "\n<Placemark>\n";
+    $link = curPageURL() . '/../trip.php?tripid=' . htmlspecialchars($tripid);
+    echo "<name>" . $stop['arrival_time'] . " @ " . htmlspecialchars($stop['stop_name']) . "</name>";
+    echo '<atom:link rel="related" href="' . $link . '"/>';
+    echo '<description><![CDATA[ <a href="' . $link . '">' . htmlspecialchars($stop['stop_name']) . "</a>]]> </description>";
+    echo "<styleUrl>#blue-pushpin</styleUrl>";
+    echo "<Point><coordinates>" . $stop['stop_lon'] . "," . $stop['stop_lat'] . "</coordinates></Point>";
+
+    echo "</Placemark>\n";
+}
+echo "</Document></kml>\n";
+?>
+
+

--- a/include/common-auth.inc.php
+++ b/include/common-auth.inc.php
@@ -30,4 +30,4 @@
         login();
          } 
     } 
-?>
+

--- a/include/common-db.inc.php
+++ b/include/common-db.inc.php
@@ -36,5 +36,4 @@
 include ('db/trip-dao.inc.php');
 include ('db/stop-dao.inc.php');
 include ('db/servicealert-dao.inc.php');
-?>
 

--- a/include/common-geo.inc.php
+++ b/include/common-geo.inc.php
@@ -168,5 +168,3 @@
     return $contents->features[0]->properties->name;
 }
 
-?>
-

--- a/include/common-net.inc.php
+++ b/include/common-net.inc.php
@@ -35,7 +35,6 @@
     debug(print_r($page, true), "json");
     return $page;
 }
-
 function curPageURL() {
     $isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on");
     $port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443")));
@@ -44,5 +43,4 @@
     return $url;
 }
 
-?>
 

--- a/include/common-request.inc.php
+++ b/include/common-request.inc.php
@@ -72,4 +72,4 @@
 if (isset($_REQUEST['geolocate'])) {
     $geolocate = filter_var($_REQUEST['geolocate'], FILTER_SANITIZE_URL);
 }
-?>
+

--- a/include/common-session.inc.php
+++ b/include/common-session.inc.php
@@ -62,10 +62,9 @@
 
 //debug(print_r($_SESSION, true) , "session");
 function current_time($time = "") {
-    if ($_REQUEST['time']) return $_REQUEST['time'];
+    if (isset($_REQUEST['time'])) return $_REQUEST['time'];
     else if ($time != "") date("H:i:s",$time);
     else return date("H:i:s");
 }
 
-?>
 

--- a/include/common-template.inc.php
+++ b/include/common-template.inc.php
@@ -54,7 +54,7 @@
 <link rel="dns-prefetch" href="//code.jquery.com">
 <link rel="dns-prefetch" href="//ajax.googleapis.com">
 	<link rel="stylesheet"  href="' . $basePath . 'css/jquery-ui-1.8.12.custom.css" />';
-    $jqmVersion = "1.0";
+    $jqmVersion = "1.0.1";
     if (isDebugServer()) {
         $jqmcss = $basePath . "css/jquery.mobile-$jqmVersion.css";
         $jqjs = $basePath . "js/jquery-1.6.4.min.js";
@@ -304,5 +304,4 @@
         return "";
     }
 }
-?>
-
+

--- a/include/common-transit.inc.php
+++ b/include/common-transit.inc.php
@@ -301,5 +301,4 @@
     }
 
 }
-?>
-
+

--- a/include/common.inc.php
+++ b/include/common.inc.php
@@ -57,7 +57,7 @@
 function isDebugServer() {
     
     return php_sapi_name() == "cli" || strstr(php_uname('n'),"actbus") || isset($_SERVER['SERVER_NAME']) && ( $_SERVER['SERVER_NAME'] == "azusa" || $_SERVER['SERVER_NAME'] == "vanille"
-            || $_SERVER['SERVER_NAME'] == "localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1" ||  $_SERVER['SERVER_NAME'] == "192.168.1.8");
+            || $_SERVER['SERVER_NAME'] == "localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1" ||  $_SERVER['SERVER_NAME'] == "192.168.1.8" || $_SERVER['SERVER_NAME'] == "192.168.178.24");
 }
 
 include_once ("common-geo.inc.php");
@@ -201,6 +201,3 @@
     return implode($glue, $retVal);
 }
 
-
-?>
-

--- a/include/db/route-dao.inc.php
+++ b/include/db/route-dao.inc.php
@@ -266,12 +266,13 @@
 }
 
 function getRoutesNearby($lat, $lng, $limit = "", $distance = 500) {
-    if ($service_period == "")
+   // if ($service_period == "")
         $service_period = service_period();
     $service_ids = service_ids($service_period);
     $sidA = $service_ids[0];
     $sidB = $service_ids[1];
-    if ($limit != "")
+ $limitSQL = "";
+    if ($limit != "") 	
         $limitSQL = " LIMIT :limit ";
     global $conn;
     $query = "SELECT service_id,trips.route_id,trips.direction_id,route_short_name,route_long_name,min(stops.stop_id) as stop_id,
@@ -299,4 +300,3 @@
     return $query->fetchAll();
 }
 
-?>

--- a/include/db/servicealert-dao.inc.php
+++ b/include/db/servicealert-dao.inc.php
@@ -174,4 +174,3 @@
     return null;
 }
 
-?>

--- a/include/db/stop-dao.inc.php
+++ b/include/db/stop-dao.inc.php
@@ -247,4 +247,3 @@
     return $timedTrips;
 }
 
-?>

--- a/include/db/trip-dao.inc.php
+++ b/include/db/trip-dao.inc.php
@@ -35,7 +35,7 @@
 }
 function getTripStops($tripID) {
     global $conn;
-    $query = "SELECT stop_id, stop_name, ST_AsKML(position) as positionkml,
+    $query = "SELECT stops.stop_id, stop_name, ST_AsKML(position) as positionkml,
 	stop_sequence, trips.trip_id
 FROM stop_times
 join trips on trips.trip_id = stop_times.trip_id
@@ -49,7 +49,7 @@
         databaseError($conn->errorInfo());
         return Array();
     }
-    return $query->fetchColumn(0);
+    return $query->fetchAll();
 }
 function getTripShape($tripID) {
     // todo, use shapes table if shape_id specified
@@ -78,7 +78,7 @@
 join trips on trips.trip_id = stop_times.trip_id
 join routes on trips.route_id = routes.route_id
 join stops on stops.stop_id = stop_times.stop_id
-WHERE trips.trip_id = :tripID $range ORDER BY stop_sequence";
+WHERE trips.trip_id = :tripID ORDER BY stop_sequence";
     debug($query, "database");
     $query = $conn->prepare($query);
     $query->bindParam(":tripID", $tripID);
@@ -203,6 +203,3 @@
     }
     return $query->fetchAll();
 }
-
-
-?>

directory:b/js/FlashCanvas (new)
--- /dev/null
+++ b/js/FlashCanvas

file:a/js/flot/excanvas.js (deleted)
--- a/js/flot/excanvas.js
+++ /dev/null
@@ -1,1428 +1,1 @@
-// Copyright 2006 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
 
-
-// Known Issues:
-//
-// * Patterns only support repeat.
-// * Radial gradient are not implemented. The VML version of these look very
-//   different from the canvas one.
-// * Clipping paths are not implemented.
-// * Coordsize. The width and height attribute have higher priority than the
-//   width and height style values which isn't correct.
-// * Painting mode isn't implemented.
-// * Canvas width/height should is using content-box by default. IE in
-//   Quirks mode will draw the canvas using border-box. Either change your
-//   doctype to HTML5
-//   (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
-//   or use Box Sizing Behavior from WebFX
-//   (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
-// * Non uniform scaling does not correctly scale strokes.
-// * Filling very large shapes (above 5000 points) is buggy.
-// * Optimize. There is always room for speed improvements.
-
-// Only add this code if we do not already have a canvas implementation
-if (!document.createElement('canvas').getContext) {
-
-(function() {
-
-  // alias some functions to make (compiled) code shorter
-  var m = Math;
-  var mr = m.round;
-  var ms = m.sin;
-  var mc = m.cos;
-  var abs = m.abs;
-  var sqrt = m.sqrt;
-
-  // this is used for sub pixel precision
-  var Z = 10;
-  var Z2 = Z / 2;
-
-  /**
-   * This funtion is assigned to the <canvas> elements as element.getContext().
-   * @this {HTMLElement}
-   * @return {CanvasRenderingContext2D_}
-   */
-  function getContext() {
-    return this.context_ ||
-        (this.context_ = new CanvasRenderingContext2D_(this));
-  }
-
-  var slice = Array.prototype.slice;
-
-  /**
-   * Binds a function to an object. The returned function will always use the
-   * passed in {@code obj} as {@code this}.
-   *
-   * Example:
-   *
-   *   g = bind(f, obj, a, b)
-   *   g(c, d) // will do f.call(obj, a, b, c, d)
-   *
-   * @param {Function} f The function to bind the object to
-   * @param {Object} obj The object that should act as this when the function
-   *     is called
-   * @param {*} var_args Rest arguments that will be used as the initial
-   *     arguments when the function is called
-   * @return {Function} A new function that has bound this
-   */
-  function bind(f, obj, var_args) {
-    var a = slice.call(arguments, 2);
-    return function() {
-      return f.apply(obj, a.concat(slice.call(arguments)));
-    };
-  }
-
-  function encodeHtmlAttribute(s) {
-    return String(s).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
-  }
-
-  function addNamespacesAndStylesheet(doc) {
-    // create xmlns
-    if (!doc.namespaces['g_vml_']) {
-      doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml',
-                         '#default#VML');
-
-    }
-    if (!doc.namespaces['g_o_']) {
-      doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office',
-                         '#default#VML');
-    }
-
-    // Setup default CSS.  Only add one style sheet per document
-    if (!doc.styleSheets['ex_canvas_']) {
-      var ss = doc.createStyleSheet();
-      ss.owningElement.id = 'ex_canvas_';
-      ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +
-          // default size is 300x150 in Gecko and Opera
-          'text-align:left;width:300px;height:150px}';
-    }
-  }
-
-  // Add namespaces and stylesheet at startup.
-  addNamespacesAndStylesheet(document);
-
-  var G_vmlCanvasManager_ = {
-    init: function(opt_doc) {
-      if (/MSIE/.test(navigator.userAgent) && !window.opera) {
-        var doc = opt_doc || document;
-        // Create a dummy element so that IE will allow canvas elements to be
-        // recognized.
-        doc.createElement('canvas');
-        doc.attachEvent('onreadystatechange', bind(this.init_, this, doc));
-      }
-    },
-
-    init_: function(doc) {
-      // find all canvas elements
-      var els = doc.getElementsByTagName('canvas');
-      for (var i = 0; i < els.length; i++) {
-        this.initElement(els[i]);
-      }
-    },
-
-    /**
-     * Public initializes a canvas element so that it can be used as canvas
-     * element from now on. This is called automatically before the page is
-     * loaded but if you are creating elements using createElement you need to
-     * make sure this is called on the element.
-     * @param {HTMLElement} el The canvas element to initialize.
-     * @return {HTMLElement} the element that was created.
-     */
-    initElement: function(el) {
-      if (!el.getContext) {
-        el.getContext = getContext;
-
-        // Add namespaces and stylesheet to document of the element.
-        addNamespacesAndStylesheet(el.ownerDocument);
-
-        // Remove fallback content. There is no way to hide text nodes so we
-        // just remove all childNodes. We could hide all elements and remove
-        // text nodes but who really cares about the fallback content.
-        el.innerHTML = '';
-
-        // do not use inline function because that will leak memory
-        el.attachEvent('onpropertychange', onPropertyChange);
-        el.attachEvent('onresize', onResize);
-
-        var attrs = el.attributes;
-        if (attrs.width && attrs.width.specified) {
-          // TODO: use runtimeStyle and coordsize
-          // el.getContext().setWidth_(attrs.width.nodeValue);
-          el.style.width = attrs.width.nodeValue + 'px';
-        } else {
-          el.width = el.clientWidth;
-        }
-        if (attrs.height && attrs.height.specified) {
-          // TODO: use runtimeStyle and coordsize
-          // el.getContext().setHeight_(attrs.height.nodeValue);
-          el.style.height = attrs.height.nodeValue + 'px';
-        } else {
-          el.height = el.clientHeight;
-        }
-        //el.getContext().setCoordsize_()
-      }
-      return el;
-    }
-  };
-
-  function onPropertyChange(e) {
-    var el = e.srcElement;
-
-    switch (e.propertyName) {
-      case 'width':
-        el.getContext().clearRect();
-        el.style.width = el.attributes.width.nodeValue + 'px';
-        // In IE8 this does not trigger onresize.
-        el.firstChild.style.width =  el.clientWidth + 'px';
-        break;
-      case 'height':
-        el.getContext().clearRect();
-        el.style.height = el.attributes.height.nodeValue + 'px';
-        el.firstChild.style.height = el.clientHeight + 'px';
-        break;
-    }
-  }
-
-  function onResize(e) {
-    var el = e.srcElement;
-    if (el.firstChild) {
-      el.firstChild.style.width =  el.clientWidth + 'px';
-      el.firstChild.style.height = el.clientHeight + 'px';
-    }
-  }
-
-  G_vmlCanvasManager_.init();
-
-  // precompute "00" to "FF"
-  var decToHex = [];
-  for (var i = 0; i < 16; i++) {
-    for (var j = 0; j < 16; j++) {
-      decToHex[i * 16 + j] = i.toString(16) + j.toString(16);
-    }
-  }
-
-  function createMatrixIdentity() {
-    return [
-      [1, 0, 0],
-      [0, 1, 0],
-      [0, 0, 1]
-    ];
-  }
-
-  function matrixMultiply(m1, m2) {
-    var result = createMatrixIdentity();
-
-    for (var x = 0; x < 3; x++) {
-      for (var y = 0; y < 3; y++) {
-        var sum = 0;
-
-        for (var z = 0; z < 3; z++) {
-          sum += m1[x][z] * m2[z][y];
-        }
-
-        result[x][y] = sum;
-      }
-    }
-    return result;
-  }
-
-  function copyState(o1, o2) {
-    o2.fillStyle     = o1.fillStyle;
-    o2.lineCap       = o1.lineCap;
-    o2.lineJoin      = o1.lineJoin;
-    o2.lineWidth     = o1.lineWidth;
-    o2.miterLimit    = o1.miterLimit;
-    o2.shadowBlur    = o1.shadowBlur;
-    o2.shadowColor   = o1.shadowColor;
-    o2.shadowOffsetX = o1.shadowOffsetX;
-    o2.shadowOffsetY = o1.shadowOffsetY;
-    o2.strokeStyle   = o1.strokeStyle;
-    o2.globalAlpha   = o1.globalAlpha;
-    o2.font          = o1.font;
-    o2.textAlign     = o1.textAlign;
-    o2.textBaseline  = o1.textBaseline;
-    o2.arcScaleX_    = o1.arcScaleX_;
-    o2.arcScaleY_    = o1.arcScaleY_;
-    o2.lineScale_    = o1.lineScale_;
-  }
-
-  var colorData = {
-    aliceblue: '#F0F8FF',
-    antiquewhite: '#FAEBD7',
-    aquamarine: '#7FFFD4',
-    azure: '#F0FFFF',
-    beige: '#F5F5DC',
-    bisque: '#FFE4C4',
-    black: '#000000',
-    blanchedalmond: '#FFEBCD',
-    blueviolet: '#8A2BE2',
-    brown: '#A52A2A',
-    burlywood: '#DEB887',
-    cadetblue: '#5F9EA0',
-    chartreuse: '#7FFF00',
-    chocolate: '#D2691E',
-    coral: '#FF7F50',
-    cornflowerblue: '#6495ED',
-    cornsilk: '#FFF8DC',
-    crimson: '#DC143C',
-    cyan: '#00FFFF',
-    darkblue: '#00008B',
-    darkcyan: '#008B8B',
-    darkgoldenrod: '#B8860B',
-    darkgray: '#A9A9A9',
-    darkgreen: '#006400',
-    darkgrey: '#A9A9A9',
-    darkkhaki: '#BDB76B',
-    darkmagenta: '#8B008B',
-    darkolivegreen: '#556B2F',
-    darkorange: '#FF8C00',
-    darkorchid: '#9932CC',
-    darkred: '#8B0000',
-    darksalmon: '#E9967A',
-    darkseagreen: '#8FBC8F',
-    darkslateblue: '#483D8B',
-    darkslategray: '#2F4F4F',
-    darkslategrey: '#2F4F4F',
-    darkturquoise: '#00CED1',
-    darkviolet: '#9400D3',
-    deeppink: '#FF1493',
-    deeps