Integrate supplier piechart
Integrate supplier piechart

file:a/about.php -> file:b/about.php
--- a/about.php
+++ b/about.php
@@ -19,13 +19,12 @@
 orem ipsum dolor sit amet, consectetuer adipiscing elit orem ipsum dolor sit amet, consectetuer adipiscing elit

 </div>

 </div>

+<?php CNDistributionGraph(); ?>

+sourced from austender

 

-sourced from austender

 Government Agency Information (2009-07-10): National Archives of Australia, http://www.naa.gov.au under Creative Commons - Attribution 2.5 Australia (CC-BY)

-jpgraph for php

+

 ABR

-Redhat Liberation fonts

-

 

 <?php

 include_once("./lib/common.inc.php");


file:a/admin/displayUNSPSC.php (deleted)
--- a/admin/displayUNSPSC.php
+++ /dev/null
@@ -1,24 +1,1 @@
-<?php

-error_reporting(E_ALL);

-  include_once("../lib/common.inc.php");

-

-

-$unspscresult= $conn->prepare('select * from "UNSPSCcategories";');

-$unspscresult->execute();

-foreach ($unspscresult->fetchAll() as $row) {

-	$unspsc[$row['UNSPSC']] = $row['Title'];

-

-}

-$catsresult = $conn->prepare('SELECT substr( "categoryUNSPSC"::text, 0, 2 ) as cat , SUM( "value" ) as value

-FROM contractnotice

-GROUP BY cat ;');

-echo "<table>";

-$catsresult->execute();

-foreach ($catsresult->fetchAll() as $row) {

-	$catName = $unspsc[$row['cat']."0000000"].$row['cat'];

-	if ($row['cat'] == "") $catName = "null";

-	

-	echo "<tr><td>$catName</td><td>".$row['value']."</td></tr>";

-}

-?>

 

--- a/admin/import.php
+++ b/admin/import.php
@@ -60,6 +60,7 @@
                       if (($datamapping0711[$headers[$c]]) == "parentCN" || ($datamapping0711[$headers[$c]]) == "CNID") {
                           $data[$c] = substr($data[$c], 2); // take off the "CN" prefix
                           $data[$c] = str_replace("-A","00",$data[$c]); // make amendments really big numbers
+                          if (!is_numeric($data[$c])) die ($data[$c]." is not numeric");
                           if ($data[$c] > 0) {
                               $contractNoticeInsert[] = $data[$c];
                           } else {
@@ -166,5 +167,13 @@
       echo "<br> $success records successfully created";
       flush();
   }
+  // run post import data processing
+  // cn
+  include("linkAmendments.php");
+  include("updateUNSPSC.php");
+// agency
+  include("setAgencyStatus.php");
+  include("setAgencyURLABN.php");
+  
 ?>
 

--- a/admin/importUNSPSC.php
+++ b/admin/importUNSPSC.php
@@ -1,5 +1,26 @@
 <?php
   include_once("../lib/common.inc.php");
+
+  // display existing
+
+$unspscresult= $conn->prepare('select * from "UNSPSCcategories";');
+$unspscresult->execute();
+foreach ($unspscresult->fetchAll() as $row) {
+  $unspsc[$row['UNSPSC']] = $row['Title'];
+
+}
+$catsresult = $conn->prepare('SELECT substr( "categoryUNSPSC"::text, 0, 2 ) as cat , SUM( "value" ) as value
+FROM contractnotice
+GROUP BY cat ;');
+echo "<table>";
+$catsresult->execute();
+foreach ($catsresult->fetchAll() as $row) {
+  $catName = $unspsc[$row['cat']."0000000"].$row['cat'];
+  if ($row['cat'] == "") $catName = "null";
+  
+  echo "<tr><td>$catName</td><td>".$row['value']."</td></tr>";
+}
+// import new from file
       $success = 0;
       $fname = "UNSPSC_ECCMA_V13.2_UNDP_V7.csv";
       echo " ============== $fname  ============== <br>";

--- a/admin/linkAmendments.php
+++ b/admin/linkAmendments.php
@@ -1,17 +1,22 @@
 <?php
 include_once ("../lib/common.inc.php");
-$query = 'SELECT "CNID","parentCN","amendmentReason" FROM contractnotice WHERE
-"parentCN" > 0 ';
+$query = 'SELECT c."CNID",c."parentCN",c."amendmentReason",p."childCN" FROM contractnotice as c  LEFT OUTER JOIN contractnotice as p on c."parentCN" = p."CNID"
+WHERE
+c."parentCN" > 0 AND p."childCN" IS NULL ';
 $query = $conn->prepare($query);
 	$query->execute();
 	if (!$query) {
 		databaseError($conn->errorInfo());
 	}
 foreach ($query->fetchAll() as $row) {
-  $conn->exec('UPDATE contractnotice SET childCN = "' .
-			 $row['CNID'] . '", amendmentReason = "' .
-			 $row['amendmentReason'] . '" where "CNID" = "' .
-			 $row['parentCN'] . '";');
+  $conn->exec('UPDATE contractnotice SET "childCN" = \'' .
+			 $row['CNID'] . '\', "amendmentReason" = \'' .
+			 $row['amendmentReason'] . '\' where "CNID" = \'' .
+			 $row['parentCN'] . '\';');
+			 echo 'UPDATE contractnotice SET "childCN" = \'' .
+			 $row['CNID'] . '\', "amendmentReason" = \'' .
+			 $row['amendmentReason'] . '\' where "CNID" = \'' .
+			 $row['parentCN'] . '\';';
     $errors = $conn->errorInfo();
               
               if ($errors[1] == 7 || $errors[1] ==0)
@@ -20,4 +25,5 @@
   else print_r($errors);
 
 }
+// also need to eliminate CN 100528/100529 - check for double parent CNs with no childCN, latest sequent CN id wins childCN = 0
 ?>

--- a/displayAgency.php
+++ b/displayAgency.php
@@ -4,9 +4,9 @@
     

 include_header("Agency");

   $agency = htmlentities(strip_tags($_REQUEST['agency']));

-  echo '<img src="graphs/displayMethodCountGraph.php?agency=' . stripslashes($agency) . '">';

-  echo '<img src="graphs/displayCnCGraph.php?agency=' . stripslashes($agency) . '">';

-  echo '<img src="graphs/displayMethodValueGraph.php?agency=' . stripslashes($agency) . '">';

+  MethodCountGraph($agency);

+  CnCGraph($agency);

+  MethodValueGraph($agency);

   /*biggest contracts

   spending by year

   spending by industry/category

@@ -63,6 +63,7 @@
      split by portfolio

     */

 include_header("Agencies");

+agenciesGraph();

   $query = 'SELECT SUM("value"), "agencyName"

 FROM contractnotice

 WHERE "childCN" = 0


--- a/displayCalendar.php
+++ b/displayCalendar.php
@@ -6,15 +6,23 @@
 if ($_REQUEST['month']) {

     echo "<center><h1>".$_REQUEST['month']."</h1></center>";

 $monthParts = explode("-",$_REQUEST['month']);

-  $query = "SELECT CNID, description, value, agencyName, category, contractStart, supplierName

-    FROM `contractnotice`

-    WHERE childCN = 0 

-    AND YEAR(contractStart) = {$monthParts[1]}

-    AND MONTH(contractStart)  = {$monthParts[0]}

-    ORDER BY value DESC";

-  $result = mysql_query($query);

-echo '<img src="graphs/displayMethodCountGraph.php?month=' . stripslashes($supplier) . '">';

-   echo '<img src="graphs/displayCnCGraph.php?month=' . stripslashes($supplier) . '">';

+  $query = 'SELECT "CNID", "description", "value", "agencyName", "category", "contractStart", "supplierName"

+    FROM contractnotice

+    WHERE "childCN" = 0 

+    AND extract(year from "contractStart") = :year

+    AND extract(month from "contractStart")  = :month

+    ORDER BY value DESC';

+$query = $conn->prepare($query);

+$query->bindParam(":month",  $monthParts[0]);

+

+$query->bindParam(":year",  $monthParts[1]);

+  $query->execute();

+  if (!$query) {

+    databaseError($conn->errorInfo());

+  }

+

+MethodCountGraph($supplier);

+CnCGraph($supplier);

 

   echo "<table>  <thead>

     <tr>

@@ -26,7 +34,7 @@
       <th>Supplier</th>

     </tr>

   </thead>";

-  while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {

+  foreach ($query->fetchAll() as $row) {

     setlocale(LC_MONETARY, 'en_US');

     $value = number_format(doubleval($row['value']) , 2);

     echo ("<tr>

@@ -52,10 +60,14 @@
 echo '<img src="graphs/displayContractPublishedGraph.php">';

 

 

-$query = "SELECT YEAR(contractStart), MONTH(contractStart),

-SUM(value) as val, count(1) as count FROM `contractnotice` WHERE childCN = 0 GROUP BY MONTH(contractStart), YEAR(contractStart) ORDER BY YEAR(contractStart), MONTH(contractStart) ";

+$query = 'SELECT extract(year from "contractStart"), extract(month from "contractStart"),

+SUM(value) as val, count(1) as count FROM contractnotice WHERE "childCN" = 0 GROUP BY extract(year from "contractStart"), extract(month from "contractStart") ORDER BY extract(year from "contractStart"), extract(month from "contractStart") ';

+$query = $conn->prepare($query);

+  $query->execute();

+  if (!$query) {

+    databaseError($conn->errorInfo());

+  }

 

-$result = mysql_query($query);

   echo "<table>  <thead>

     <tr>

       <th>Month/Year</th>

@@ -63,7 +75,7 @@
       <th>Number of Contracts</th>

     </tr>

   </thead>";

-while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {

+  foreach ($query->fetchAll() as $row) {

 setlocale(LC_MONETARY, 'en_US');

 $value = number_format(doubleval($row["val"]),2);

 $month_name = date( 'F', mktime(0, 0, 0, $row[1]) );


--- a/displayHeatmap.php
+++ b/displayHeatmap.php
@@ -1,7 +1,7 @@
 <?php

 

 

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

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

 

 $year = 2006;

 $ZeroX = 112.5;

@@ -22,12 +22,17 @@
 $height = 457;

 //echo "http://dev.openstreetmap.org/~pafciu17/?module=map&bbox=".$ZeroX.",".$ZeroY.",".$MaxX.",".$MaxY."&width=".$width."&height=".$height;

 //$handle = ImageCreate ($width, $height) or die ("Cannot Create image");

-$handle = imagecreatefrompng('../images/australia.png');

+$handle = imagecreatefrompng('images/australia.png');

 $white = imagecolorallocate($handle, 0, 0, 0);

 imagecolortransparent($handle, $white);

 

-$query = "SELECT supplierPostcode, sum(value) as value, lat, lon FROM `contractnotice`,`postcodes` where childCN = 0 AND supplierCountry = 'Australia' AND YEAR(contractStart) >= '$year' AND supplierPostcode = postcode GROUP BY supplierPostcode";

-$result = mysql_query($query);

+$query = 'SELECT "supplierPostcode", sum("value") as value, max(lat) as lat, max(lon) as lon FROM contractnotice inner join postcodes on "supplierPostcode" = postcode::text where "childCN" = 0 AND "supplierCountry" = \'Australia\' GROUP BY "supplierPostcode"';

+$query = $conn->prepare($query);

+   $query->execute();

+   if (!$query) {

+      databaseError($conn->errorInfo());

+   }

+

 

 $left = "FFFF50";

 $right= "EF0050";

@@ -41,8 +46,7 @@
     $colorset[$i] = imagecolorallocatealpha($handle, $leftR + ($i*(($rightR-$leftR)/250)), $leftG + ($i*(($rightG-$leftG)/250)), $leftB + ($i*(($rightB-$leftB)/250)),117 - ($i/250)*40);

 }

 

-while ($row = mysql_fetch_array($result, MYSQL_BOTH))

-{

+  foreach ($query->fetchAll() as $row) {

    $xpage = round((($XRange - ($MaxX - $row['lon'])) / $xdivlength));

 	if ($row['lat'] < -40.25) $row['lat']-= 0.75;

    $ypage = round(($YRange - (abs($MaxY) - abs($row['lat']))) / $ydivheight);


--- a/displaySupplier.php
+++ b/displaySupplier.php
@@ -4,9 +4,9 @@
     
 include_header("Supplier");
   $supplierS = htmlentities(strip_tags($_REQUEST['supplier']));
-  echo '<img src="graphs/displayMethodCountGraph.php?supplier=' . stripslashes($supplierS) . '">';
-   echo '<img src="graphs/displayCnCGraph.php?supplier=' . stripslashes($supplierS) . '">';
-   echo '<img src="graphs/displayMethodValueGraph.php?supplier=' . stripslashes($supplierS) . '">';
+  MethodCountGraph($supplierS);
+   CnCGraph($supplierS);
+  MethodValueGraph($supplierS);
   /*lobbyist ties
   
   links to ABR/ASIC/Google News/ASX/Court records
@@ -62,6 +62,7 @@
      histograph of supplier size/value
     */
 include_header("Suppliers");
+suppliersGraph();
   $query = 'SELECT SUM("value") as val, MAX("supplierName") as supplierName, "supplierABN",(
  case when "supplierABN" != 0 THEN "supplierABN"::text ELSE "supplierName" END) as supplierID 
 FROM contractnotice

--- a/lib/common.inc.php
+++ b/lib/common.inc.php
@@ -207,5 +207,6 @@
    echo '<div id="ft"><p>'."Processing time: ". sprintf("%.4f", ($end-$start))." seconds".'</p></div>'; 

    echo '</div> </body> </html>';

 } 

+include ("graphs.inc.php");

 ?>

 

--- /dev/null
+++ b/lib/flot/excanvas.js
@@ -1,1 +1,1428 @@
-
+// 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',
+    deepskyblue: '#00BFFF',
+    dimgray: '#696969',
+    dimgrey: '#696969',
+    dodgerblue: '#1E90FF',
+    firebrick: '#B22222',
+    floralwhite: '#FFFAF0',
+    forestgreen: '#228B22',
+    gainsboro: '#DCDCDC',
+    ghostwhite: '#F8F8FF',
+    gold: '#FFD700',
+    goldenrod: '#DAA520',
+    grey: '#808080',
+    greenyellow: '#ADFF2F',
+    honeydew: '#F0FFF0',
+    hotpink: '#FF69B4',
+    indianred: '#CD5C5C',
+    indigo: '#4B0082',
+    ivory: '#FFFFF0',
+    khaki: '#F0E68C',
+    lavender: '#E6E6FA',
+    lavenderblush: '#FFF0F5',
+    lawngreen: '#7CFC00',
+    lemonchiffon: '#FFFACD',
+    lightblue: '#ADD8E6',
+    lightcoral: '#F08080',
+    lightcyan: '#E0FFFF',
+    lightgoldenrodyellow: '#FAFAD2',
+    lightgreen: '#90EE90',
+    lightgrey: '#D3D3D3',
+    lightpink: '#FFB6C1',
+    lightsalmon: '#FFA07A',
+    lightseagreen: '#20B2AA',
+    lightskyblue: '#87CEFA',
+    lightslategray: '#778899',
+    lightslategrey: '#778899',
+    lightsteelblue: '#B0C4DE',
+    lightyellow: '#FFFFE0',
+    limegreen: '#32CD32',
+    linen: '#FAF0E6',
+    magenta: '#FF00FF',
+    mediumaquamarine: '#66CDAA',
+    mediumblue: '#0000CD',
+    mediumorchid: '#BA55D3',
+    mediumpurple: '#9370DB',
+    mediumseagreen: '#3CB371',
+    mediumslateblue: '#7B68EE',
+    mediumspringgreen: '#00FA9A',
+    mediumturquoise: '#48D1CC',
+    mediumvioletred: '#C71585',
+    midnightblue: '#191970',
+    mintcream: '#F5FFFA',
+    mistyrose: '#FFE4E1',
+    moccasin: '#FFE4B5',
+    navajowhite: '#FFDEAD',
+    oldlace: '#FDF5E6',
+    olivedrab: '#6B8E23',
+    orange: '#FFA500',
+    orangered: '#FF4500',
+    orchid: '#DA70D6',
+    palegoldenrod: '#EEE8AA',
+    palegreen: '#98FB98',
+    paleturquoise: '#AFEEEE',
+    palevioletred: '#DB7093',
+    papayawhip: '#FFEFD5',
+    peachpuff: '#FFDAB9',
+    peru: '#CD853F',
+    pink: '#FFC0CB',
+    plum: '#DDA0DD',
+    powderblue: '#B0E0E6',
+    rosybrown: '#BC8F8F',
+    royalblue: '#4169E1',
+    saddlebrown: '#8B4513',
+    salmon: '#FA8072',
+    sandybrown: '#F4A460',
+    seagreen: '#2E8B57',
+    seashell: '#FFF5EE',
+    sienna: '#A0522D',
+    skyblue: '#87CEEB',
+    slateblue: '#6A5ACD',
+    slategray: '#708090',
+    slategrey: '#708090',
+    snow: '#FFFAFA',
+    springgreen: '#00FF7F',
+    steelblue: '#4682B4',
+    tan: '#D2B48C',
+    thistle: '#D8BFD8',
+    tomato: '#FF6347',
+    turquoise: '#40E0D0',
+    violet: '#EE82EE',
+    wheat: '#F5DEB3',
+    whitesmoke: '#F5F5F5',
+    yellowgreen: '#9ACD32'
+  };
+
+
+  function getRgbHslContent(styleString) {
+    var start = styleString.indexOf('(', 3);
+    var end = styleString.indexOf(')', start + 1);
+    var parts = styleString.substring(start + 1, end).split(',');
+    // add alpha if needed
+    if (parts.length == 4 && styleString.substr(3, 1) == 'a') {
+      alpha = Number(parts[3]);
+    } else {
+      parts[3] = 1;
+    }
+    return parts;
+  }
+
+  function percent(s) {
+    return parseFloat(s) / 100;
+  }
+
+  function clamp(v, min, max) {
+    return Math.min(max, Math.max(min, v));
+  }
+
+  function hslToRgb(parts){
+    var r, g, b;
+    h = parseFloat(parts[0]) / 360 % 360;
+    if (h < 0)
+      h++;
+    s = clamp(percent(parts[1]), 0, 1);
+    l = clamp(percent(parts[2]), 0, 1);
+    if (s == 0) {
+      r = g = b = l; // achromatic
+    } else {
+      var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+      var p = 2 * l - q;
+      r = hueToRgb(p, q, h + 1 / 3);
+      g = hueToRgb(p, q, h);
+      b = hueToRgb(p, q, h - 1 / 3);
+    }
+
+    return '#' + decToHex[Math.floor(r * 255)] +
+        decToHex[Math.floor(g * 255)] +
+        decToHex[Math.floor(b * 255)];
+  }
+
+  function hueToRgb(m1, m2, h) {
+    if (h < 0)
+      h++;
+    if (h > 1)
+      h--;
+
+    if (6 * h < 1)
+      return m1 + (m2 - m1) * 6 * h;
+    else if (2 * h < 1)
+      return m2;
+    else if (3 * h < 2)
+      return m1 + (m2 - m1) * (2 / 3 - h) * 6;
+    else
+      return m1;
+  }
+
+  function processStyle(styleString) {
+    var str, alpha = 1;
+
+    styleString = String(styleString);
+    if (styleString.charAt(0) == '#') {
+      str = styleString;
+    } else if (/^rgb/.test(styleString)) {
+      var parts = getRgbHslContent(styleString);
+      var str = '#', n;
+      for (var i = 0; i < 3; i++) {
+        if (parts[i].indexOf('%') != -1) {
+          n = Math.floor(percent(parts[i]) * 255);
+        } else {
+          n = Number(parts[i]);
+        }
+        str += decToHex[clamp(n, 0, 255)];
+      }
+      alpha = parts[3];
+    } else if (/^hsl/.test(styleString)) {
+      var parts = getRgbHslContent(styleString);
+      str = hslToRgb(parts);
+      alpha = parts[3];
+    } else {
+      str = colorData[styleString] || styleString;
+    }
+    return {color: str, alpha: alpha};
+  }
+
+  var DEFAULT_STYLE = {
+    style: 'normal',
+    variant: 'normal',
+    weight: 'normal',
+    size: 10,
+    family: 'sans-serif'
+  };
+
+  // Internal text style cache
+  var fontStyleCache = {};