Difference between revisions of "Team:Munich/backgroundGraphics/p5JS"

(Created page with "! p5.js v0.5.4 October 01, 2016: (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd)...")
 
(No difference)

Latest revision as of 14:56, 7 September 2019

/*! p5.js v0.5.4 October 01, 2016 */ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.p5 = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){

},{}],2:[function(_dereq_,module,exports){ // Run-time checking of preconditions.

'use strict';

// Precondition function that checks if the given predicate is true. // If not, it will throw an error. exports.argument = function(predicate, message) {

   if (!predicate) {
       throw new Error(message);
   }

};

// Precondition function that checks if the given assertion is true. // If not, it will throw an error. exports.assert = exports.argument;

},{}],3:[function(_dereq_,module,exports){ // Drawing utility functions.

'use strict';

// Draw a line on the given context from point `x1,y1` to point `x2,y2`. function line(ctx, x1, y1, x2, y2) {

   ctx.beginPath();
   ctx.moveTo(x1, y1);
   ctx.lineTo(x2, y2);
   ctx.stroke();

}

exports.line = line;

},{}],4:[function(_dereq_,module,exports){ // Glyph encoding

'use strict';

var cffStandardStrings = [

   '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright',
   'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',
   'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater',
   'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
   'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
   'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
   'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', 'sterling',
   'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft',
   'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', 'periodcentered', 'paragraph',
   'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand',
   'questiondown', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', 'ring',
   'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE',
   'ordmasculine', 'ae', 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',
   'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn',
   'threequarters', 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',
   'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex',
   'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',
   'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute',
   'Ydieresis', 'Zcaron', 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', 'eacute',
   'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute',
   'ocircumflex', 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', 'ugrave',
   'yacute', 'ydieresis', 'zcaron', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior',
   'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', '266 ff', 'onedotenleader',
   'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle',
   'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior', 'threequartersemdash', 'periodsuperior',
   'questionsmall', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
   'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'ffi', 'ffl',
   'parenleftinferior', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall',
   'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall',
   'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
   'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall',
   'centoldstyle', 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall',
   'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall',
   'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds',
   'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
   'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior',
   'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior',
   'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall',
   'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall',
   'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall',
   'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall',
   'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall', '001.000',
   '001.001', '001.002', '001.003', 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'];

var cffStandardEncoding = [

   , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
   , , , , 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright',
   'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',
   'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater',
   'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
   'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
   'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
   'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', , , , , , , , ,
   , , , , , , , , , , , , , , , , , , , , , , , , , ,
   'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle',
   'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', , 'endash', 'dagger',
   'daggerdbl', 'periodcentered', , 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright',
   'guillemotright', 'ellipsis', 'perthousand', , 'questiondown', , 'grave', 'acute', 'circumflex', 'tilde',
   'macron', 'breve', 'dotaccent', 'dieresis', , 'ring', 'cedilla', , 'hungarumlaut', 'ogonek', 'caron',
   'emdash', , , , , , , , , , , , , , , , , 'AE', , 'ordfeminine', , , ,
   , 'Lslash', 'Oslash', 'OE', 'ordmasculine', , , , , , 'ae', , , , 'dotlessi', , ,
   'lslash', 'oslash', 'oe', 'germandbls'];

var cffExpertEncoding = [

   , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
   , , , , 'space', 'exclamsmall', 'Hungarumlautsmall', , 'dollaroldstyle', 'dollarsuperior',
   'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader',
   'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
   'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon',
   'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', , 'asuperior',
   'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', , , 'isuperior', , , 'lsuperior', 'msuperior',
   'nsuperior', 'osuperior', , , 'rsuperior', 'ssuperior', 'tsuperior', , 'ff', 'fi', 'fl', 'ffi', 'ffl',
   'parenleftinferior', , 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall',
   'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall',
   'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
   'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', , , , , , , ,
   , , , , , , , , , , , , , , , , , , , , , , , , , , ,
   'exclamdownsmall', 'centoldstyle', 'Lslashsmall', , , 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',
   'Brevesmall', 'Caronsmall', , 'Dotaccentsmall', , , 'Macronsmall', , , 'figuredash', 'hypheninferior',
   , , 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', , , , 'onequarter', 'onehalf', 'threequarters',
   'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', ,
   , 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
   'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',
   'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior',
   'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',
   'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall',
   'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
   'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall',
   'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
   'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall'];

var standardNames = [

   '.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
   'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',
   'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
   'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
   'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
   'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
   'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
   'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', 'Udieresis', 'aacute', 'agrave',
   'acircumflex', 'adieresis', 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis',
   'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex', 'odieresis',
   'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section',
   'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', 'dieresis', 'notequal',
   'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation',
   'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', 'questiondown',
   'exclamdown', 'logicalnot', 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', 'guillemotright',
   'ellipsis', 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft',
   'quotedblright', 'quoteleft', 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction',
   'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered', 'quotesinglbase',
   'quotedblbase', 'perthousand', 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute',
   'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', 'Ucircumflex',
   'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut',
   'ogonek', 'caron', 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar', 'Eth', 'eth',
   'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply', 'onesuperior', 'twosuperior', 'threesuperior',
   'onehalf', 'onequarter', 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla', 'scedilla',
   'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat'];

// This is the encoding used for fonts created from scratch. // It loops through all glyphs and finds the appropriate unicode value. // Since it's linear time, other encodings will be faster. function DefaultEncoding(font) {

   this.font = font;

}

DefaultEncoding.prototype.charToGlyphIndex = function(c) {

   var code = c.charCodeAt(0);
   var glyphs = this.font.glyphs;
   if (glyphs) {
       for (var i = 0; i < glyphs.length; i += 1) {
           var glyph = glyphs.get(i);
           for (var j = 0; j < glyph.unicodes.length; j += 1) {
               if (glyph.unicodes[j] === code) {
                   return i;
               }
           }
       }
   } else {
       return null;
   }

};

function CmapEncoding(cmap) {

   this.cmap = cmap;

}

CmapEncoding.prototype.charToGlyphIndex = function(c) {

   return this.cmap.glyphIndexMap[c.charCodeAt(0)] || 0;

};

function CffEncoding(encoding, charset) {

   this.encoding = encoding;
   this.charset = charset;

}

CffEncoding.prototype.charToGlyphIndex = function(s) {

   var code = s.charCodeAt(0);
   var charName = this.encoding[code];
   return this.charset.indexOf(charName);

};

function GlyphNames(post) {

   var i;
   switch (post.version) {
   case 1:
       this.names = exports.standardNames.slice();
       break;
   case 2:
       this.names = new Array(post.numberOfGlyphs);
       for (i = 0; i < post.numberOfGlyphs; i++) {
           if (post.glyphNameIndex[i] < exports.standardNames.length) {
               this.names[i] = exports.standardNames[post.glyphNameIndex[i]];
           } else {
               this.names[i] = post.names[post.glyphNameIndex[i] - exports.standardNames.length];
           }
       }
       break;
   case 2.5:
       this.names = new Array(post.numberOfGlyphs);
       for (i = 0; i < post.numberOfGlyphs; i++) {
           this.names[i] = exports.standardNames[i + post.glyphNameIndex[i]];
       }
       break;
   case 3:
       this.names = [];
       break;
   }

}

GlyphNames.prototype.nameToGlyphIndex = function(name) {

   return this.names.indexOf(name);

};

GlyphNames.prototype.glyphIndexToName = function(gid) {

   return this.names[gid];

};

function addGlyphNames(font) {

   var glyph;
   var glyphIndexMap = font.tables.cmap.glyphIndexMap;
   var charCodes = Object.keys(glyphIndexMap);
   for (var i = 0; i < charCodes.length; i += 1) {
       var c = charCodes[i];
       var glyphIndex = glyphIndexMap[c];
       glyph = font.glyphs.get(glyphIndex);
       glyph.addUnicode(parseInt(c));
   }
   for (i = 0; i < font.glyphs.length; i += 1) {
       glyph = font.glyphs.get(i);
       if (font.cffEncoding) {
           glyph.name = font.cffEncoding.charset[i];
       } else {
           glyph.name = font.glyphNames.glyphIndexToName(i);
       }
   }

}

exports.cffStandardStrings = cffStandardStrings; exports.cffStandardEncoding = cffStandardEncoding; exports.cffExpertEncoding = cffExpertEncoding; exports.standardNames = standardNames; exports.DefaultEncoding = DefaultEncoding; exports.CmapEncoding = CmapEncoding; exports.CffEncoding = CffEncoding; exports.GlyphNames = GlyphNames; exports.addGlyphNames = addGlyphNames;

},{}],5:[function(_dereq_,module,exports){ // The Font object

'use strict';

var path = _dereq_('./path'); var sfnt = _dereq_('./tables/sfnt'); var encoding = _dereq_('./encoding'); var glyphset = _dereq_('./glyphset');

// A Font represents a loaded OpenType font file. // It contains a set of glyphs and methods to draw text on a drawing context, // or to get a path representing the text. function Font(options) {

   options = options || {};
   // OS X will complain if the names are empty, so we put a single space everywhere by default.
   this.familyName = options.familyName || ' ';
   this.styleName = options.styleName || ' ';
   this.designer = options.designer || ' ';
   this.designerURL = options.designerURL || ' ';
   this.manufacturer = options.manufacturer || ' ';
   this.manufacturerURL = options.manufacturerURL || ' ';
   this.license = options.license || ' ';
   this.licenseURL = options.licenseURL || ' ';
   this.version = options.version || 'Version 0.1';
   this.description = options.description || ' ';
   this.copyright = options.copyright || ' ';
   this.trademark = options.trademark || ' ';
   this.unitsPerEm = options.unitsPerEm || 1000;
   this.ascender = options.ascender;
   this.descender = options.descender;
   this.supported = true;
   this.glyphs = new glyphset.GlyphSet(this, options.glyphs || []);
   this.encoding = new encoding.DefaultEncoding(this);
   this.tables = {};

}

// Check if the font has a glyph for the given character. Font.prototype.hasChar = function(c) {

   return this.encoding.charToGlyphIndex(c) !== null;

};

// Convert the given character to a single glyph index. // Note that this function assumes that there is a one-to-one mapping between // the given character and a glyph; for complex scripts this might not be the case. Font.prototype.charToGlyphIndex = function(s) {

   return this.encoding.charToGlyphIndex(s);

};

// Convert the given character to a single Glyph object. // Note that this function assumes that there is a one-to-one mapping between // the given character and a glyph; for complex scripts this might not be the case. Font.prototype.charToGlyph = function(c) {

   var glyphIndex = this.charToGlyphIndex(c);
   var glyph = this.glyphs.get(glyphIndex);
   if (!glyph) {
       // .notdef
       glyph = this.glyphs.get(0);
   }
   return glyph;

};

// Convert the given text to a list of Glyph objects. // Note that there is no strict one-to-one mapping between characters and // glyphs, so the list of returned glyphs can be larger or smaller than the // length of the given string. Font.prototype.stringToGlyphs = function(s) {

   var glyphs = [];
   for (var i = 0; i < s.length; i += 1) {
       var c = s[i];
       glyphs.push(this.charToGlyph(c));
   }
   return glyphs;

};

Font.prototype.nameToGlyphIndex = function(name) {

   return this.glyphNames.nameToGlyphIndex(name);

};

Font.prototype.nameToGlyph = function(name) {

   var glyphIndex = this.nametoGlyphIndex(name);
   var glyph = this.glyphs.get(glyphIndex);
   if (!glyph) {
       // .notdef
       glyph = this.glyphs.get(0);
   }
   return glyph;

};

Font.prototype.glyphIndexToName = function(gid) {

   if (!this.glyphNames.glyphIndexToName) {
       return ;
   }
   return this.glyphNames.glyphIndexToName(gid);

};

// Retrieve the value of the kerning pair between the left glyph (or its index) // and the right glyph (or its index). If no kerning pair is found, return 0. // The kerning value gets added to the advance width when calculating the spacing // between glyphs. Font.prototype.getKerningValue = function(leftGlyph, rightGlyph) {

   leftGlyph = leftGlyph.index || leftGlyph;
   rightGlyph = rightGlyph.index || rightGlyph;
   var gposKerning = this.getGposKerningValue;
   return gposKerning ? gposKerning(leftGlyph, rightGlyph) :
       (this.kerningPairs[leftGlyph + ',' + rightGlyph] || 0);

};

// Helper function that invokes the given callback for each glyph in the given text. // The callback gets `(glyph, x, y, fontSize, options)`. Font.prototype.forEachGlyph = function(text, x, y, fontSize, options, callback) {

   if (!this.supported) {
       return;
   }
   x = x !== undefined ? x : 0;
   y = y !== undefined ? y : 0;
   fontSize = fontSize !== undefined ? fontSize : 72;
   options = options || {};
   var kerning = options.kerning === undefined ? true : options.kerning;
   var fontScale = 1 / this.unitsPerEm * fontSize;
   var glyphs = this.stringToGlyphs(text);
   for (var i = 0; i < glyphs.length; i += 1) {
       var glyph = glyphs[i];
       callback(glyph, x, y, fontSize, options);
       if (glyph.advanceWidth) {
           x += glyph.advanceWidth * fontScale;
       }
       if (kerning && i < glyphs.length - 1) {
           var kerningValue = this.getKerningValue(glyph, glyphs[i + 1]);
           x += kerningValue * fontScale;
       }
   }

};

// Create a Path object that represents the given text. // // text - The text to create. // x - Horizontal position of the beginning of the text. (default: 0) // y - Vertical position of the *baseline* of the text. (default: 0) // fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72) // Options is an optional object that contains: // - kerning - Whether to take kerning information into account. (default: true) // // Returns a Path object. Font.prototype.getPath = function(text, x, y, fontSize, options) {

   var fullPath = new path.Path();
   this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
       var glyphPath = glyph.getPath(gX, gY, gFontSize);
       fullPath.extend(glyphPath);
   });
   return fullPath;

};

// Draw the text on the given drawing context. // // ctx - A 2D drawing context, like Canvas. // text - The text to create. // x - Horizontal position of the beginning of the text. (default: 0) // y - Vertical position of the *baseline* of the text. (default: 0) // fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72) // Options is an optional object that contains: // - kerning - Whether to take kerning information into account. (default: true) Font.prototype.draw = function(ctx, text, x, y, fontSize, options) {

   this.getPath(text, x, y, fontSize, options).draw(ctx);

};

// Draw the points of all glyphs in the text. // On-curve points will be drawn in blue, off-curve points will be drawn in red. // // ctx - A 2D drawing context, like Canvas. // text - The text to create. // x - Horizontal position of the beginning of the text. (default: 0) // y - Vertical position of the *baseline* of the text. (default: 0) // fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72) // Options is an optional object that contains: // - kerning - Whether to take kerning information into account. (default: true) Font.prototype.drawPoints = function(ctx, text, x, y, fontSize, options) {

   this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
       glyph.drawPoints(ctx, gX, gY, gFontSize);
   });

};

// Draw lines indicating important font measurements for all glyphs in the text. // Black lines indicate the origin of the coordinate system (point 0,0). // Blue lines indicate the glyph bounding box. // Green line indicates the advance width of the glyph. // // ctx - A 2D drawing context, like Canvas. // text - The text to create. // x - Horizontal position of the beginning of the text. (default: 0) // y - Vertical position of the *baseline* of the text. (default: 0) // fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72) // Options is an optional object that contains: // - kerning - Whether to take kerning information into account. (default: true) Font.prototype.drawMetrics = function(ctx, text, x, y, fontSize, options) {

   this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
       glyph.drawMetrics(ctx, gX, gY, gFontSize);
   });

};

// Validate Font.prototype.validate = function() {

   var warnings = [];
   var _this = this;
   function assert(predicate, message) {
       if (!predicate) {
           warnings.push(message);
       }
   }
   function assertStringAttribute(attrName) {
       assert(_this[attrName] && _this[attrName].trim().length > 0, 'No ' + attrName + ' specified.');
   }
   // Identification information
   assertStringAttribute('familyName');
   assertStringAttribute('weightName');
   assertStringAttribute('manufacturer');
   assertStringAttribute('copyright');
   assertStringAttribute('version');
   // Dimension information
   assert(this.unitsPerEm > 0, 'No unitsPerEm specified.');

};

// Convert the font object to a SFNT data structure. // This structure contains all the necessary tables and metadata to create a binary OTF file. Font.prototype.toTables = function() {

   return sfnt.fontToTable(this);

};

Font.prototype.toBuffer = function() {

   var sfntTable = this.toTables();
   var bytes = sfntTable.encode();
   var buffer = new ArrayBuffer(bytes.length);
   var intArray = new Uint8Array(buffer);
   for (var i = 0; i < bytes.length; i++) {
       intArray[i] = bytes[i];
   }
   return buffer;

};

// Initiate a download of the OpenType font. Font.prototype.download = function() {

   var fileName = this.familyName.replace(/\s/g, ) + '-' + this.styleName + '.otf';
   var buffer = this.toBuffer();
   window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
   window.requestFileSystem(window.TEMPORARY, buffer.byteLength, function(fs) {
       fs.root.getFile(fileName, {create: true}, function(fileEntry) {
           fileEntry.createWriter(function(writer) {
               var dataView = new DataView(buffer);
               var blob = new Blob([dataView], {type: 'font/opentype'});
               writer.write(blob);
               writer.addEventListener('writeend', function() {
                   // Navigating to the file will download it.
                   location.href = fileEntry.toURL();
               }, false);
           });
       });
   },
   function(err) {
       throw err;
   });

};

exports.Font = Font;

},{"./encoding":4,"./glyphset":7,"./path":10,"./tables/sfnt":25}],6:[function(_dereq_,module,exports){ // The Glyph object

'use strict';

var check = _dereq_('./check'); var draw = _dereq_('./draw'); var path = _dereq_('./path');

function getPathDefinition(glyph, path) {

   var _path = path || { commands: [] };
   return {
       configurable: true,
       get: function() {
           if (typeof _path === 'function') {
               _path = _path();
           }
           return _path;
       },
       set: function(p) {
           _path = p;
       }
   };

}

// A Glyph is an individual mark that often corresponds to a character. // Some glyphs, such as ligatures, are a combination of many characters. // Glyphs are the basic building blocks of a font. // // The `Glyph` class contains utility methods for drawing the path and its points. function Glyph(options) {

   // By putting all the code on a prototype function (which is only declared once)
   // we reduce the memory requirements for larger fonts by some 2%
   this.bindConstructorValues(options);

}

Glyph.prototype.bindConstructorValues = function(options) {

   this.index = options.index || 0;
   // These three values cannnot be deferred for memory optimization:
   this.name = options.name || null;
   this.unicode = options.unicode || undefined;
   this.unicodes = options.unicodes || options.unicode !== undefined ? [options.unicode] : [];
   // But by binding these values only when necessary, we reduce can
   // the memory requirements by almost 3% for larger fonts.
   if (options.xMin) {
       this.xMin = options.xMin;
   }
   if (options.yMin) {
       this.yMin = options.yMin;
   }
   if (options.xMax) {
       this.xMax = options.xMax;
   }
   if (options.yMax) {
       this.yMax = options.yMax;
   }
   if (options.advanceWidth) {
       this.advanceWidth = options.advanceWidth;
   }
   // The path for a glyph is the most memory intensive, and is bound as a value
   // with a getter/setter to ensure we actually do path parsing only once the
   // path is actually needed by anything.
   Object.defineProperty(this, 'path', getPathDefinition(this, options.path));

};

Glyph.prototype.addUnicode = function(unicode) {

   if (this.unicodes.length === 0) {
       this.unicode = unicode;
   }
   this.unicodes.push(unicode);

};

// Convert the glyph to a Path we can draw on a drawing context. // // x - Horizontal position of the glyph. (default: 0) // y - Vertical position of the *baseline* of the glyph. (default: 0) // fontSize - Font size, in pixels (default: 72). Glyph.prototype.getPath = function(x, y, fontSize) {

   x = x !== undefined ? x : 0;
   y = y !== undefined ? y : 0;
   fontSize = fontSize !== undefined ? fontSize : 72;
   var scale = 1 / this.path.unitsPerEm * fontSize;
   var p = new path.Path();
   var commands = this.path.commands;
   for (var i = 0; i < commands.length; i += 1) {
       var cmd = commands[i];
       if (cmd.type === 'M') {
           p.moveTo(x + (cmd.x * scale), y + (-cmd.y * scale));
       } else if (cmd.type === 'L') {
           p.lineTo(x + (cmd.x * scale), y + (-cmd.y * scale));
       } else if (cmd.type === 'Q') {
           p.quadraticCurveTo(x + (cmd.x1 * scale), y + (-cmd.y1 * scale),
                              x + (cmd.x * scale), y + (-cmd.y * scale));
       } else if (cmd.type === 'C') {
           p.curveTo(x + (cmd.x1 * scale), y + (-cmd.y1 * scale),
                     x + (cmd.x2 * scale), y + (-cmd.y2 * scale),
                     x + (cmd.x * scale), y + (-cmd.y * scale));
       } else if (cmd.type === 'Z') {
           p.closePath();
       }
   }
   return p;

};

// Split the glyph into contours. // This function is here for backwards compatibility, and to // provide raw access to the TrueType glyph outlines. Glyph.prototype.getContours = function() {

   if (this.points === undefined) {
       return [];
   }
   var contours = [];
   var currentContour = [];
   for (var i = 0; i < this.points.length; i += 1) {
       var pt = this.points[i];
       currentContour.push(pt);
       if (pt.lastPointOfContour) {
           contours.push(currentContour);
           currentContour = [];
       }
   }
   check.argument(currentContour.length === 0, 'There are still points left in the current contour.');
   return contours;

};

// Calculate the xMin/yMin/xMax/yMax/lsb/rsb for a Glyph. Glyph.prototype.getMetrics = function() {

   var commands = this.path.commands;
   var xCoords = [];
   var yCoords = [];
   for (var i = 0; i < commands.length; i += 1) {
       var cmd = commands[i];
       if (cmd.type !== 'Z') {
           xCoords.push(cmd.x);
           yCoords.push(cmd.y);
       }
       if (cmd.type === 'Q' || cmd.type === 'C') {
           xCoords.push(cmd.x1);
           yCoords.push(cmd.y1);
       }
       if (cmd.type === 'C') {
           xCoords.push(cmd.x2);
           yCoords.push(cmd.y2);
       }
   }
   var metrics = {
       xMin: Math.min.apply(null, xCoords),
       yMin: Math.min.apply(null, yCoords),
       xMax: Math.max.apply(null, xCoords),
       yMax: Math.max.apply(null, yCoords),
       leftSideBearing: 0
   };
   metrics.rightSideBearing = this.advanceWidth - metrics.leftSideBearing - (metrics.xMax - metrics.xMin);
   return metrics;

};

// Draw the glyph on the given context. // // ctx - The drawing context. // x - Horizontal position of the glyph. (default: 0) // y - Vertical position of the *baseline* of the glyph. (default: 0) // fontSize - Font size, in pixels (default: 72). Glyph.prototype.draw = function(ctx, x, y, fontSize) {

   this.getPath(x, y, fontSize).draw(ctx);

};

// Draw the points of the glyph. // On-curve points will be drawn in blue, off-curve points will be drawn in red. // // ctx - The drawing context. // x - Horizontal position of the glyph. (default: 0) // y - Vertical position of the *baseline* of the glyph. (default: 0) // fontSize - Font size, in pixels (default: 72). Glyph.prototype.drawPoints = function(ctx, x, y, fontSize) {

   function drawCircles(l, x, y, scale) {
       var PI_SQ = Math.PI * 2;
       ctx.beginPath();
       for (var j = 0; j < l.length; j += 1) {
           ctx.moveTo(x + (l[j].x * scale), y + (l[j].y * scale));
           ctx.arc(x + (l[j].x * scale), y + (l[j].y * scale), 2, 0, PI_SQ, false);
       }
       ctx.closePath();
       ctx.fill();
   }
   x = x !== undefined ? x : 0;
   y = y !== undefined ? y : 0;
   fontSize = fontSize !== undefined ? fontSize : 24;
   var scale = 1 / this.path.unitsPerEm * fontSize;
   var blueCircles = [];
   var redCircles = [];
   var path = this.path;
   for (var i = 0; i < path.commands.length; i += 1) {
       var cmd = path.commands[i];
       if (cmd.x !== undefined) {
           blueCircles.push({x: cmd.x, y: -cmd.y});
       }
       if (cmd.x1 !== undefined) {
           redCircles.push({x: cmd.x1, y: -cmd.y1});
       }
       if (cmd.x2 !== undefined) {
           redCircles.push({x: cmd.x2, y: -cmd.y2});
       }
   }
   ctx.fillStyle = 'blue';
   drawCircles(blueCircles, x, y, scale);
   ctx.fillStyle = 'red';
   drawCircles(redCircles, x, y, scale);

};

// Draw lines indicating important font measurements. // Black lines indicate the origin of the coordinate system (point 0,0). // Blue lines indicate the glyph bounding box. // Green line indicates the advance width of the glyph. // // ctx - The drawing context. // x - Horizontal position of the glyph. (default: 0) // y - Vertical position of the *baseline* of the glyph. (default: 0) // fontSize - Font size, in pixels (default: 72). Glyph.prototype.drawMetrics = function(ctx, x, y, fontSize) {

   var scale;
   x = x !== undefined ? x : 0;
   y = y !== undefined ? y : 0;
   fontSize = fontSize !== undefined ? fontSize : 24;
   scale = 1 / this.path.unitsPerEm * fontSize;
   ctx.lineWidth = 1;
   // Draw the origin
   ctx.strokeStyle = 'black';
   draw.line(ctx, x, -10000, x, 10000);
   draw.line(ctx, -10000, y, 10000, y);
   // This code is here due to memory optimization: by not using
   // defaults in the constructor, we save a notable amount of memory.
   var xMin = this.xMin || 0;
   var yMin = this.yMin || 0;
   var xMax = this.xMax || 0;
   var yMax = this.yMax || 0;
   var advanceWidth = this.advanceWidth || 0;
   // Draw the glyph box
   ctx.strokeStyle = 'blue';
   draw.line(ctx, x + (xMin * scale), -10000, x + (xMin * scale), 10000);
   draw.line(ctx, x + (xMax * scale), -10000, x + (xMax * scale), 10000);
   draw.line(ctx, -10000, y + (-yMin * scale), 10000, y + (-yMin * scale));
   draw.line(ctx, -10000, y + (-yMax * scale), 10000, y + (-yMax * scale));
   // Draw the advance width
   ctx.strokeStyle = 'green';
   draw.line(ctx, x + (advanceWidth * scale), -10000, x + (advanceWidth * scale), 10000);

};

exports.Glyph = Glyph;

},{"./check":2,"./draw":3,"./path":10}],7:[function(_dereq_,module,exports){ // The GlyphSet object

'use strict';

var _glyph = _dereq_('./glyph');

// A GlyphSet represents all glyphs available in the font, but modelled using // a deferred glyph loader, for retrieving glyphs only once they are absolutely // necessary, to keep the memory footprint down. function GlyphSet(font, glyphs) {

   this.font = font;
   this.glyphs = {};
   if (Array.isArray(glyphs)) {
       for (var i = 0; i < glyphs.length; i++) {
           this.glyphs[i] = glyphs[i];
       }
   }
   this.length = (glyphs && glyphs.length) || 0;

}

GlyphSet.prototype.get = function(index) {

   if (typeof this.glyphs[index] === 'function') {
       this.glyphs[index] = this.glyphs[index]();
   }
   return this.glyphs[index];

};

GlyphSet.prototype.push = function(index, loader) {

   this.glyphs[index] = loader;
   this.length++;

};

function glyphLoader(font, index) {

   return new _glyph.Glyph({index: index, font: font});

}

/**

* Generate a stub glyph that can be filled with all metadata *except*
* the "points" and "path" properties, which must be loaded only once
* the glyph's path is actually requested for text shaping.
*/

function ttfGlyphLoader(font, index, parseGlyph, data, position, buildPath) {

   return function() {
       var glyph = new _glyph.Glyph({index: index, font: font});
       glyph.path = function() {
           parseGlyph(glyph, data, position);
           var path = buildPath(font.glyphs, glyph);
           path.unitsPerEm = font.unitsPerEm;
           return path;
       };
       return glyph;
   };

}

function cffGlyphLoader(font, index, parseCFFCharstring, charstring) {

   return function() {
       var glyph = new _glyph.Glyph({index: index, font: font});
       glyph.path = function() {
           var path = parseCFFCharstring(font, glyph, charstring);
           path.unitsPerEm = font.unitsPerEm;
           return path;
       };
       return glyph;
   };

}

exports.GlyphSet = GlyphSet; exports.glyphLoader = glyphLoader; exports.ttfGlyphLoader = ttfGlyphLoader; exports.cffGlyphLoader = cffGlyphLoader;

},{"./glyph":6}],8:[function(_dereq_,module,exports){ // opentype.js // https://github.com/nodebox/opentype.js // (c) 2015 Frederik De Bleser // opentype.js may be freely distributed under the MIT license.

/* global ArrayBuffer, DataView, Uint8Array, XMLHttpRequest */

'use strict';

var encoding = _dereq_('./encoding'); var _font = _dereq_('./font'); var glyph = _dereq_('./glyph'); var parse = _dereq_('./parse'); var path = _dereq_('./path');

var cmap = _dereq_('./tables/cmap'); var cff = _dereq_('./tables/cff'); var glyf = _dereq_('./tables/glyf'); var gpos = _dereq_('./tables/gpos'); var head = _dereq_('./tables/head'); var hhea = _dereq_('./tables/hhea'); var hmtx = _dereq_('./tables/hmtx'); var kern = _dereq_('./tables/kern'); var loca = _dereq_('./tables/loca'); var maxp = _dereq_('./tables/maxp'); var _name = _dereq_('./tables/name'); var os2 = _dereq_('./tables/os2'); var post = _dereq_('./tables/post');

// File loaders /////////////////////////////////////////////////////////

// Convert a Node.js Buffer to an ArrayBuffer function toArrayBuffer(buffer) {

   var arrayBuffer = new ArrayBuffer(buffer.length);
   var data = new Uint8Array(arrayBuffer);
   for (var i = 0; i < buffer.length; i += 1) {
       data[i] = buffer[i];
   }
   return arrayBuffer;

}

function loadFromFile(path, callback) {

   var fs = _dereq_('fs');
   fs.readFile(path, function(err, buffer) {
       if (err) {
           return callback(err.message);
       }
       callback(null, toArrayBuffer(buffer));
   });

}

function loadFromUrl(url, callback) {

   var request = new XMLHttpRequest();
   request.open('get', url, true);
   request.responseType = 'arraybuffer';
   request.onload = function() {
       if (request.status !== 200) {
           return callback('Font could not be loaded: ' + request.statusText);
       }
       return callback(null, request.response);
   };
   request.send();

}

// Public API ///////////////////////////////////////////////////////////

// Parse the OpenType file data (as an ArrayBuffer) and return a Font object. // If the file could not be parsed (most likely because it contains Postscript outlines) // we return an empty Font object with the `supported` flag set to `false`. function parseBuffer(buffer) {

   var indexToLocFormat;
   var hmtxOffset;
   var glyfOffset;
   var locaOffset;
   var cffOffset;
   var kernOffset;
   var gposOffset;
   // OpenType fonts use big endian byte ordering.
   // We can't rely on typed array view types, because they operate with the endianness of the host computer.
   // Instead we use DataViews where we can specify endianness.
   var font = new _font.Font();
   var data = new DataView(buffer, 0);
   var version = parse.getFixed(data, 0);
   if (version === 1.0) {
       font.outlinesFormat = 'truetype';
   } else {
       version = parse.getTag(data, 0);
       if (version === 'OTTO') {
           font.outlinesFormat = 'cff';
       } else {
           throw new Error('Unsupported OpenType version ' + version);
       }
   }
   var numTables = parse.getUShort(data, 4);
   // Offset into the table records.
   var p = 12;
   for (var i = 0; i < numTables; i += 1) {
       var tag = parse.getTag(data, p);
       var offset = parse.getULong(data, p + 8);
       switch (tag) {
       case 'cmap':
           font.tables.cmap = cmap.parse(data, offset);
           font.encoding = new encoding.CmapEncoding(font.tables.cmap);
           if (!font.encoding) {
               font.supported = false;
           }
           break;
       case 'head':
           font.tables.head = head.parse(data, offset);
           font.unitsPerEm = font.tables.head.unitsPerEm;
           indexToLocFormat = font.tables.head.indexToLocFormat;
           break;
       case 'hhea':
           font.tables.hhea = hhea.parse(data, offset);
           font.ascender = font.tables.hhea.ascender;
           font.descender = font.tables.hhea.descender;
           font.numberOfHMetrics = font.tables.hhea.numberOfHMetrics;
           break;
       case 'hmtx':
           hmtxOffset = offset;
           break;
       case 'maxp':
           font.tables.maxp = maxp.parse(data, offset);
           font.numGlyphs = font.tables.maxp.numGlyphs;
           break;
       case 'name':
           font.tables.name = _name.parse(data, offset);
           font.familyName = font.tables.name.fontFamily;
           font.styleName = font.tables.name.fontSubfamily;
           break;
       case 'OS/2':
           font.tables.os2 = os2.parse(data, offset);
           break;
       case 'post':
           font.tables.post = post.parse(data, offset);
           font.glyphNames = new encoding.GlyphNames(font.tables.post);
           break;
       case 'glyf':
           glyfOffset = offset;
           break;
       case 'loca':
           locaOffset = offset;
           break;
       case 'CFF ':
           cffOffset = offset;
           break;
       case 'kern':
           kernOffset = offset;
           break;
       case 'GPOS':
           gposOffset = offset;
           break;
       }
       p += 16;
   }
   if (glyfOffset && locaOffset) {
       var shortVersion = indexToLocFormat === 0;
       var locaTable = loca.parse(data, locaOffset, font.numGlyphs, shortVersion);
       font.glyphs = glyf.parse(data, glyfOffset, locaTable, font);
       hmtx.parse(data, hmtxOffset, font.numberOfHMetrics, font.numGlyphs, font.glyphs);
       encoding.addGlyphNames(font);
   } else if (cffOffset) {
       cff.parse(data, cffOffset, font);
       encoding.addGlyphNames(font);
   } else {
       font.supported = false;
   }
   if (font.supported) {
       if (kernOffset) {
           font.kerningPairs = kern.parse(data, kernOffset);
       } else {
           font.kerningPairs = {};
       }
       if (gposOffset) {
           gpos.parse(data, gposOffset, font);
       }
   }
   return font;

}

// Asynchronously load the font from a URL or a filesystem. When done, call the callback // with two arguments `(err, font)`. The `err` will be null on success, // the `font` is a Font object. // // We use the node.js callback convention so that // opentype.js can integrate with frameworks like async.js. function load(url, callback) {

   var isNode = typeof window === 'undefined';
   var loadFn = isNode ? loadFromFile : loadFromUrl;
   loadFn(url, function(err, arrayBuffer) {
       if (err) {
           return callback(err);
       }
       var font = parseBuffer(arrayBuffer);
       if (!font.supported) {
           return callback('Font is not supported (is this a Postscript font?)');
       }
       return callback(null, font);
   });

}

exports._parse = parse; exports.Font = _font.Font; exports.Glyph = glyph.Glyph; exports.Path = path.Path; exports.parse = parseBuffer; exports.load = load;

},{"./encoding":4,"./font":5,"./glyph":6,"./parse":9,"./path":10,"./tables/cff":12,"./tables/cmap":13,"./tables/glyf":14,"./tables/gpos":15,"./tables/head":16,"./tables/hhea":17,"./tables/hmtx":18,"./tables/kern":19,"./tables/loca":20,"./tables/maxp":21,"./tables/name":22,"./tables/os2":23,"./tables/post":24,"fs":1}],9:[function(_dereq_,module,exports){ // Parsing utility functions

'use strict';

// Retrieve an unsigned byte from the DataView. exports.getByte = function getByte(dataView, offset) {

   return dataView.getUint8(offset);

};

exports.getCard8 = exports.getByte;

// Retrieve an unsigned 16-bit short from the DataView. // The value is stored in big endian. exports.getUShort = function(dataView, offset) {

   return dataView.getUint16(offset, false);

};

exports.getCard16 = exports.getUShort;

// Retrieve a signed 16-bit short from the DataView. // The value is stored in big endian. exports.getShort = function(dataView, offset) {

   return dataView.getInt16(offset, false);

};

// Retrieve an unsigned 32-bit long from the DataView. // The value is stored in big endian. exports.getULong = function(dataView, offset) {

   return dataView.getUint32(offset, false);

};

// Retrieve a 32-bit signed fixed-point number (16.16) from the DataView. // The value is stored in big endian. exports.getFixed = function(dataView, offset) {

   var decimal = dataView.getInt16(offset, false);
   var fraction = dataView.getUint16(offset + 2, false);
   return decimal + fraction / 65535;

};

// Retrieve a 4-character tag from the DataView. // Tags are used to identify tables. exports.getTag = function(dataView, offset) {

   var tag = ;
   for (var i = offset; i < offset + 4; i += 1) {
       tag += String.fromCharCode(dataView.getInt8(i));
   }
   return tag;

};

// Retrieve an offset from the DataView. // Offsets are 1 to 4 bytes in length, depending on the offSize argument. exports.getOffset = function(dataView, offset, offSize) {

   var v = 0;
   for (var i = 0; i < offSize; i += 1) {
       v <<= 8;
       v += dataView.getUint8(offset + i);
   }
   return v;

};

// Retrieve a number of bytes from start offset to the end offset from the DataView. exports.getBytes = function(dataView, startOffset, endOffset) {

   var bytes = [];
   for (var i = startOffset; i < endOffset; i += 1) {
       bytes.push(dataView.getUint8(i));
   }
   return bytes;

};

// Convert the list of bytes to a string. exports.bytesToString = function(bytes) {

   var s = ;
   for (var i = 0; i < bytes.length; i += 1) {
       s += String.fromCharCode(bytes[i]);
   }
   return s;

};

var typeOffsets = {

   byte: 1,
   uShort: 2,
   short: 2,
   uLong: 4,
   fixed: 4,
   longDateTime: 8,
   tag: 4

};

// A stateful parser that changes the offset whenever a value is retrieved. // The data is a DataView. function Parser(data, offset) {

   this.data = data;
   this.offset = offset;
   this.relativeOffset = 0;

}

Parser.prototype.parseByte = function() {

   var v = this.data.getUint8(this.offset + this.relativeOffset);
   this.relativeOffset += 1;
   return v;

};

Parser.prototype.parseChar = function() {

   var v = this.data.getInt8(this.offset + this.relativeOffset);
   this.relativeOffset += 1;
   return v;

};

Parser.prototype.parseCard8 = Parser.prototype.parseByte;

Parser.prototype.parseUShort = function() {

   var v = this.data.getUint16(this.offset + this.relativeOffset);
   this.relativeOffset += 2;
   return v;

};

Parser.prototype.parseCard16 = Parser.prototype.parseUShort; Parser.prototype.parseSID = Parser.prototype.parseUShort; Parser.prototype.parseOffset16 = Parser.prototype.parseUShort;

Parser.prototype.parseShort = function() {

   var v = this.data.getInt16(this.offset + this.relativeOffset);
   this.relativeOffset += 2;
   return v;

};

Parser.prototype.parseF2Dot14 = function() {

   var v = this.data.getInt16(this.offset + this.relativeOffset) / 16384;
   this.relativeOffset += 2;
   return v;

};

Parser.prototype.parseULong = function() {

   var v = exports.getULong(this.data, this.offset + this.relativeOffset);
   this.relativeOffset += 4;
   return v;

};

Parser.prototype.parseFixed = function() {

   var v = exports.getFixed(this.data, this.offset + this.relativeOffset);
   this.relativeOffset += 4;
   return v;

};

Parser.prototype.parseOffset16List = Parser.prototype.parseUShortList = function(count) {

   var offsets = new Array(count);
   var dataView = this.data;
   var offset = this.offset + this.relativeOffset;
   for (var i = 0; i < count; i++) {
       offsets[i] = exports.getUShort(dataView, offset);
       offset += 2;
   }
   this.relativeOffset += count * 2;
   return offsets;

};

Parser.prototype.parseString = function(length) {

   var dataView = this.data;
   var offset = this.offset + this.relativeOffset;
   var string = ;
   this.relativeOffset += length;
   for (var i = 0; i < length; i++) {
       string += String.fromCharCode(dataView.getUint8(offset + i));
   }
   return string;

};

Parser.prototype.parseTag = function() {

   return this.parseString(4);

};

// LONGDATETIME is a 64-bit integer. // JavaScript and unix timestamps traditionally use 32 bits, so we // only take the last 32 bits. Parser.prototype.parseLongDateTime = function() {

   var v = exports.getULong(this.data, this.offset + this.relativeOffset + 4);
   this.relativeOffset += 8;
   return v;

};

Parser.prototype.parseFixed = function() {

   var v = exports.getULong(this.data, this.offset + this.relativeOffset);
   this.relativeOffset += 4;
   return v / 65536;

};

Parser.prototype.parseVersion = function() {

   var major = exports.getUShort(this.data, this.offset + this.relativeOffset);
   // How to interpret the minor version is very vague in the spec. 0x5000 is 5, 0x1000 is 1
   // This returns the correct number if minor = 0xN000 where N is 0-9
   var minor = exports.getUShort(this.data, this.offset + this.relativeOffset + 2);
   this.relativeOffset += 4;
   return major + minor / 0x1000 / 10;

};

Parser.prototype.skip = function(type, amount) {

   if (amount === undefined) {
       amount = 1;
   }
   this.relativeOffset += typeOffsets[type] * amount;

};

exports.Parser = Parser;

},{}],10:[function(_dereq_,module,exports){ // Geometric objects

'use strict';

// A bézier path containing a set of path commands similar to a SVG path. // Paths can be drawn on a context using `draw`. function Path() {

   this.commands = [];
   this.fill = 'black';
   this.stroke = null;
   this.strokeWidth = 1;

}

Path.prototype.moveTo = function(x, y) {

   this.commands.push({
       type: 'M',
       x: x,
       y: y
   });

};

Path.prototype.lineTo = function(x, y) {

   this.commands.push({
       type: 'L',
       x: x,
       y: y
   });

};

Path.prototype.curveTo = Path.prototype.bezierCurveTo = function(x1, y1, x2, y2, x, y) {

   this.commands.push({
       type: 'C',
       x1: x1,
       y1: y1,
       x2: x2,
       y2: y2,
       x: x,
       y: y
   });

};

Path.prototype.quadTo = Path.prototype.quadraticCurveTo = function(x1, y1, x, y) {

   this.commands.push({
       type: 'Q',
       x1: x1,
       y1: y1,
       x: x,
       y: y
   });

};

Path.prototype.close = Path.prototype.closePath = function() {

   this.commands.push({
       type: 'Z'
   });

};

// Add the given path or list of commands to the commands of this path. Path.prototype.extend = function(pathOrCommands) {

   if (pathOrCommands.commands) {
       pathOrCommands = pathOrCommands.commands;
   }
   Array.prototype.push.apply(this.commands, pathOrCommands);

};

// Draw the path to a 2D context. Path.prototype.draw = function(ctx) {

   ctx.beginPath();
   for (var i = 0; i < this.commands.length; i += 1) {
       var cmd = this.commands[i];
       if (cmd.type === 'M') {
           ctx.moveTo(cmd.x, cmd.y);
       } else if (cmd.type === 'L') {
           ctx.lineTo(cmd.x, cmd.y);
       } else if (cmd.type === 'C') {
           ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
       } else if (cmd.type === 'Q') {
           ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);
       } else if (cmd.type === 'Z') {
           ctx.closePath();
       }
   }
   if (this.fill) {
       ctx.fillStyle = this.fill;
       ctx.fill();
   }
   if (this.stroke) {
       ctx.strokeStyle = this.stroke;
       ctx.lineWidth = this.strokeWidth;
       ctx.stroke();
   }

};

// Convert the Path to a string of path data instructions // See http://www.w3.org/TR/SVG/paths.html#PathData // Parameters: // - decimalPlaces: The amount of decimal places for floating-point values (default: 2) Path.prototype.toPathData = function(decimalPlaces) {

   decimalPlaces = decimalPlaces !== undefined ? decimalPlaces : 2;
   function floatToString(v) {
       if (Math.round(v) === v) {
           return  + Math.round(v);
       } else {
           return v.toFixed(decimalPlaces);
       }
   }
   function packValues() {
       var s = ;
       for (var i = 0; i < arguments.length; i += 1) {
           var v = arguments[i];
           if (v >= 0 && i > 0) {
               s += ' ';
           }
           s += floatToString(v);
       }
       return s;
   }
   var d = ;
   for (var i = 0; i < this.commands.length; i += 1) {
       var cmd = this.commands[i];
       if (cmd.type === 'M') {
           d += 'M' + packValues(cmd.x, cmd.y);
       } else if (cmd.type === 'L') {
           d += 'L' + packValues(cmd.x, cmd.y);
       } else if (cmd.type === 'C') {
           d += 'C' + packValues(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
       } else if (cmd.type === 'Q') {
           d += 'Q' + packValues(cmd.x1, cmd.y1, cmd.x, cmd.y);
       } else if (cmd.type === 'Z') {
           d += 'Z';
       }
   }
   return d;

};

// Convert the path to a SVG <path> element, as a string. // Parameters: // - decimalPlaces: The amount of decimal places for floating-point values (default: 2) Path.prototype.toSVG = function(decimalPlaces) {

   var svg = '<path d="';
   svg += this.toPathData(decimalPlaces);
   svg += '"';
   if (this.fill & this.fill !== 'black') {
       if (this.fill === null) {
           svg += ' fill="none"';
       } else {
           svg += ' fill="' + this.fill + '"';
       }
   }
   if (this.stroke) {
       svg += ' stroke="' + this.stroke + '" stroke-width="' + this.strokeWidth + '"';
   }
   svg += '/>';
   return svg;

};

exports.Path = Path;

},{}],11:[function(_dereq_,module,exports){ // Table metadata

'use strict';

var check = _dereq_('./check'); var encode = _dereq_('./types').encode; var sizeOf = _dereq_('./types').sizeOf;

function Table(tableName, fields, options) {

   var i;
   for (i = 0; i < fields.length; i += 1) {
       var field = fields[i];
       this[field.name] = field.value;
   }
   this.tableName = tableName;
   this.fields = fields;
   if (options) {
       var optionKeys = Object.keys(options);
       for (i = 0; i < optionKeys.length; i += 1) {
           var k = optionKeys[i];
           var v = options[k];
           if (this[k] !== undefined) {
               this[k] = v;
           }
       }
   }

}

Table.prototype.sizeOf = function() {

   var v = 0;
   for (var i = 0; i < this.fields.length; i += 1) {
       var field = this.fields[i];
       var value = this[field.name];
       if (value === undefined) {
           value = field.value;
       }
       if (typeof value.sizeOf === 'function') {
           v += value.sizeOf();
       } else {
           var sizeOfFunction = sizeOf[field.type];
           check.assert(typeof sizeOfFunction === 'function', 'Could not find sizeOf function for field' + field.name);
           v += sizeOfFunction(value);
       }
   }
   return v;

};

Table.prototype.encode = function() {

   return encode.TABLE(this);

};

exports.Table = Table;

},{"./check":2,"./types":26}],12:[function(_dereq_,module,exports){ // The `CFF` table contains the glyph outlines in PostScript format. // https://www.microsoft.com/typography/OTSPEC/cff.htm // http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/cff.pdf // http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/type2.pdf

'use strict';

var encoding = _dereq_('../encoding'); var glyphset = _dereq_('../glyphset'); var parse = _dereq_('../parse'); var path = _dereq_('../path'); var table = _dereq_('../table');

// Custom equals function that can also check lists. function equals(a, b) {

   if (a === b) {
       return true;
   } else if (Array.isArray(a) && Array.isArray(b)) {
       if (a.length !== b.length) {
           return false;
       }
       for (var i = 0; i < a.length; i += 1) {
           if (!equals(a[i], b[i])) {
               return false;
           }
       }
       return true;
   } else {
       return false;
   }

}

// Parse a `CFF` INDEX array. // An index array consists of a list of offsets, then a list of objects at those offsets. function parseCFFIndex(data, start, conversionFn) {

   //var i, objectOffset, endOffset;
   var offsets = [];
   var objects = [];
   var count = parse.getCard16(data, start);
   var i;
   var objectOffset;
   var endOffset;
   if (count !== 0) {
       var offsetSize = parse.getByte(data, start + 2);
       objectOffset = start + ((count + 1) * offsetSize) + 2;
       var pos = start + 3;
       for (i = 0; i < count + 1; i += 1) {
           offsets.push(parse.getOffset(data, pos, offsetSize));
           pos += offsetSize;
       }
       // The total size of the index array is 4 header bytes + the value of the last offset.
       endOffset = objectOffset + offsets[count];
   } else {
       endOffset = start + 2;
   }
   for (i = 0; i < offsets.length - 1; i += 1) {
       var value = parse.getBytes(data, objectOffset + offsets[i], objectOffset + offsets[i + 1]);
       if (conversionFn) {
           value = conversionFn(value);
       }
       objects.push(value);
   }
   return {objects: objects, startOffset: start, endOffset: endOffset};

}

// Parse a `CFF` DICT real value. function parseFloatOperand(parser) {

   var s = ;
   var eof = 15;
   var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'E', 'E-', null, '-'];
   while (true) {
       var b = parser.parseByte();
       var n1 = b >> 4;
       var n2 = b & 15;
       if (n1 === eof) {
           break;
       }
       s += lookup[n1];
       if (n2 === eof) {
           break;
       }
       s += lookup[n2];
   }
   return parseFloat(s);

}

// Parse a `CFF` DICT operand. function parseOperand(parser, b0) {

   var b1;
   var b2;
   var b3;
   var b4;
   if (b0 === 28) {
       b1 = parser.parseByte();
       b2 = parser.parseByte();
       return b1 << 8 | b2;
   }
   if (b0 === 29) {
       b1 = parser.parseByte();
       b2 = parser.parseByte();
       b3 = parser.parseByte();
       b4 = parser.parseByte();
       return b1 << 24 | b2 << 16 | b3 << 8 | b4;
   }
   if (b0 === 30) {
       return parseFloatOperand(parser);
   }
   if (b0 >= 32 && b0 <= 246) {
       return b0 - 139;
   }
   if (b0 >= 247 && b0 <= 250) {
       b1 = parser.parseByte();
       return (b0 - 247) * 256 + b1 + 108;
   }
   if (b0 >= 251 && b0 <= 254) {
       b1 = parser.parseByte();
       return -(b0 - 251) * 256 - b1 - 108;
   }
   throw new Error('Invalid b0 ' + b0);

}

// Convert the entries returned by `parseDict` to a proper dictionary. // If a value is a list of one, it is unpacked. function entriesToObject(entries) {

   var o = {};
   for (var i = 0; i < entries.length; i += 1) {
       var key = entries[i][0];
       var values = entries[i][1];
       var value;
       if (values.length === 1) {
           value = values[0];
       } else {
           value = values;
       }
       if (o.hasOwnProperty(key)) {
           throw new Error('Object ' + o + ' already has key ' + key);
       }
       o[key] = value;
   }
   return o;

}

// Parse a `CFF` DICT object. // A dictionary contains key-value pairs in a compact tokenized format. function parseCFFDict(data, start, size) {

   start = start !== undefined ? start : 0;
   var parser = new parse.Parser(data, start);
   var entries = [];
   var operands = [];
   size = size !== undefined ? size : data.length;
   while (parser.relativeOffset < size) {
       var op = parser.parseByte();
       // The first byte for each dict item distinguishes between operator (key) and operand (value).
       // Values <= 21 are operators.
       if (op <= 21) {
           // Two-byte operators have an initial escape byte of 12.
           if (op === 12) {
               op = 1200 + parser.parseByte();
           }
           entries.push([op, operands]);
           operands = [];
       } else {
           // Since the operands (values) come before the operators (keys), we store all operands in a list
           // until we encounter an operator.
           operands.push(parseOperand(parser, op));
       }
   }
   return entriesToObject(entries);

}

// Given a String Index (SID), return the value of the string. // Strings below index 392 are standard CFF strings and are not encoded in the font. function getCFFString(strings, index) {

   if (index <= 390) {
       index = encoding.cffStandardStrings[index];
   } else {
       index = strings[index - 391];
   }
   return index;

}

// Interpret a dictionary and return a new dictionary with readable keys and values for missing entries. // This function takes `meta` which is a list of objects containing `operand`, `name` and `default`. function interpretDict(dict, meta, strings) {

   var newDict = {};
   // Because we also want to include missing values, we start out from the meta list
   // and lookup values in the dict.
   for (var i = 0; i < meta.length; i += 1) {
       var m = meta[i];
       var value = dict[m.op];
       if (value === undefined) {
           value = m.value !== undefined ? m.value : null;
       }
       if (m.type === 'SID') {
           value = getCFFString(strings, value);
       }
       newDict[m.name] = value;
   }
   return newDict;

}

// Parse the CFF header. function parseCFFHeader(data, start) {

   var header = {};
   header.formatMajor = parse.getCard8(data, start);
   header.formatMinor = parse.getCard8(data, start + 1);
   header.size = parse.getCard8(data, start + 2);
   header.offsetSize = parse.getCard8(data, start + 3);
   header.startOffset = start;
   header.endOffset = start + 4;
   return header;

}

var TOP_DICT_META = [

   {name: 'version', op: 0, type: 'SID'},
   {name: 'notice', op: 1, type: 'SID'},
   {name: 'copyright', op: 1200, type: 'SID'},
   {name: 'fullName', op: 2, type: 'SID'},
   {name: 'familyName', op: 3, type: 'SID'},
   {name: 'weight', op: 4, type: 'SID'},
   {name: 'isFixedPitch', op: 1201, type: 'number', value: 0},
   {name: 'italicAngle', op: 1202, type: 'number', value: 0},
   {name: 'underlinePosition', op: 1203, type: 'number', value: -100},
   {name: 'underlineThickness', op: 1204, type: 'number', value: 50},
   {name: 'paintType', op: 1205, type: 'number', value: 0},
   {name: 'charstringType', op: 1206, type: 'number', value: 2},
   {name: 'fontMatrix', op: 1207, type: ['real', 'real', 'real', 'real', 'real', 'real'], value: [0.001, 0, 0, 0.001, 0, 0]},
   {name: 'uniqueId', op: 13, type: 'number'},
   {name: 'fontBBox', op: 5, type: ['number', 'number', 'number', 'number'], value: [0, 0, 0, 0]},
   {name: 'strokeWidth', op: 1208, type: 'number', value: 0},
   {name: 'xuid', op: 14, type: [], value: null},
   {name: 'charset', op: 15, type: 'offset', value: 0},
   {name: 'encoding', op: 16, type: 'offset', value: 0},
   {name: 'charStrings', op: 17, type: 'offset', value: 0},
   {name: 'private', op: 18, type: ['number', 'offset'], value: [0, 0]}

];

var PRIVATE_DICT_META = [

   {name: 'subrs', op: 19, type: 'offset', value: 0},
   {name: 'defaultWidthX', op: 20, type: 'number', value: 0},
   {name: 'nominalWidthX', op: 21, type: 'number', value: 0}

];

// Parse the CFF top dictionary. A CFF table can contain multiple fonts, each with their own top dictionary. // The top dictionary contains the essential metadata for the font, together with the private dictionary. function parseCFFTopDict(data, strings) {

   var dict = parseCFFDict(data, 0, data.byteLength);
   return interpretDict(dict, TOP_DICT_META, strings);

}

// Parse the CFF private dictionary. We don't fully parse out all the values, only the ones we need. function parseCFFPrivateDict(data, start, size, strings) {

   var dict = parseCFFDict(data, start, size);
   return interpretDict(dict, PRIVATE_DICT_META, strings);

}

// Parse the CFF charset table, which contains internal names for all the glyphs. // This function will return a list of glyph names. // See Adobe TN #5176 chapter 13, "Charsets". function parseCFFCharset(data, start, nGlyphs, strings) {

   var i;
   var sid;
   var count;
   var parser = new parse.Parser(data, start);
   // The .notdef glyph is not included, so subtract 1.
   nGlyphs -= 1;
   var charset = ['.notdef'];
   var format = parser.parseCard8();
   if (format === 0) {
       for (i = 0; i < nGlyphs; i += 1) {
           sid = parser.parseSID();
           charset.push(getCFFString(strings, sid));
       }
   } else if (format === 1) {
       while (charset.length <= nGlyphs) {
           sid = parser.parseSID();
           count = parser.parseCard8();
           for (i = 0; i <= count; i += 1) {
               charset.push(getCFFString(strings, sid));
               sid += 1;
           }
       }
   } else if (format === 2) {
       while (charset.length <= nGlyphs) {
           sid = parser.parseSID();
           count = parser.parseCard16();
           for (i = 0; i <= count; i += 1) {
               charset.push(getCFFString(strings, sid));
               sid += 1;
           }
       }
   } else {
       throw new Error('Unknown charset format ' + format);
   }
   return charset;

}

// Parse the CFF encoding data. Only one encoding can be specified per font. // See Adobe TN #5176 chapter 12, "Encodings". function parseCFFEncoding(data, start, charset) {

   var i;
   var code;
   var enc = {};
   var parser = new parse.Parser(data, start);
   var format = parser.parseCard8();
   if (format === 0) {
       var nCodes = parser.parseCard8();
       for (i = 0; i < nCodes; i += 1) {
           code = parser.parseCard8();
           enc[code] = i;
       }
   } else if (format === 1) {
       var nRanges = parser.parseCard8();
       code = 1;
       for (i = 0; i < nRanges; i += 1) {
           var first = parser.parseCard8();
           var nLeft = parser.parseCard8();
           for (var j = first; j <= first + nLeft; j += 1) {
               enc[j] = code;
               code += 1;
           }
       }
   } else {
       throw new Error('Unknown encoding format ' + format);
   }
   return new encoding.CffEncoding(enc, charset);

}

// Take in charstring code and return a Glyph object. // The encoding is described in the Type 2 Charstring Format // https://www.microsoft.com/typography/OTSPEC/charstr2.htm function parseCFFCharstring(font, glyph, code) {

   var c1x;
   var c1y;
   var c2x;
   var c2y;
   var p = new path.Path();
   var stack = [];
   var nStems = 0;
   var haveWidth = false;
   var width = font.defaultWidthX;
   var open = false;
   var x = 0;
   var y = 0;
   function newContour(x, y) {
       if (open) {
           p.closePath();
       }
       p.moveTo(x, y);
       open = true;
   }
   function parseStems() {
       var hasWidthArg;
       // The number of stem operators on the stack is always even.
       // If the value is uneven, that means a width is specified.
       hasWidthArg = stack.length % 2 !== 0;
       if (hasWidthArg && !haveWidth) {
           width = stack.shift() + font.nominalWidthX;
       }
       nStems += stack.length >> 1;
       stack.length = 0;
       haveWidth = true;
   }
   function parse(code) {
       var b1;
       var b2;
       var b3;
       var b4;
       var codeIndex;
       var subrCode;
       var jpx;
       var jpy;
       var c3x;
       var c3y;
       var c4x;
       var c4y;
       var i = 0;
       while (i < code.length) {
           var v = code[i];
           i += 1;
           switch (v) {
           case 1: // hstem
               parseStems();
               break;
           case 3: // vstem
               parseStems();
               break;
           case 4: // vmoveto
               if (stack.length > 1 && !haveWidth) {
                   width = stack.shift() + font.nominalWidthX;
                   haveWidth = true;
               }
               y += stack.pop();
               newContour(x, y);
               break;
           case 5: // rlineto
               while (stack.length > 0) {
                   x += stack.shift();
                   y += stack.shift();
                   p.lineTo(x, y);
               }
               break;
           case 6: // hlineto
               while (stack.length > 0) {
                   x += stack.shift();
                   p.lineTo(x, y);
                   if (stack.length === 0) {
                       break;
                   }
                   y += stack.shift();
                   p.lineTo(x, y);
               }
               break;
           case 7: // vlineto
               while (stack.length > 0) {
                   y += stack.shift();
                   p.lineTo(x, y);
                   if (stack.length === 0) {
                       break;
                   }
                   x += stack.shift();
                   p.lineTo(x, y);
               }
               break;
           case 8: // rrcurveto
               while (stack.length > 0) {
                   c1x = x + stack.shift();
                   c1y = y + stack.shift();
                   c2x = c1x + stack.shift();
                   c2y = c1y + stack.shift();
                   x = c2x + stack.shift();
                   y = c2y + stack.shift();
                   p.curveTo(c1x, c1y, c2x, c2y, x, y);
               }
               break;
           case 10: // callsubr
               codeIndex = stack.pop() + font.subrsBias;
               subrCode = font.subrs[codeIndex];
               if (subrCode) {
                   parse(subrCode);
               }
               break;
           case 11: // return
               return;
           case 12: // flex operators
               v = code[i];
               i += 1;
               switch (v) {
               case 35: // flex
                   // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd flex (12 35) |-
                   c1x = x   + stack.shift();    // dx1
                   c1y = y   + stack.shift();    // dy1
                   c2x = c1x + stack.shift();    // dx2
                   c2y = c1y + stack.shift();    // dy2
                   jpx = c2x + stack.shift();    // dx3
                   jpy = c2y + stack.shift();    // dy3
                   c3x = jpx + stack.shift();    // dx4
                   c3y = jpy + stack.shift();    // dy4
                   c4x = c3x + stack.shift();    // dx5
                   c4y = c3y + stack.shift();    // dy5
                   x = c4x + stack.shift();      // dx6
                   y = c4y + stack.shift();      // dy6
                   stack.shift();                // flex depth
                   p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
                   p.curveTo(c3x, c3y, c4x, c4y, x, y);
                   break;
               case 34: // hflex
                   // |- dx1 dx2 dy2 dx3 dx4 dx5 dx6 hflex (12 34) |-
                   c1x = x   + stack.shift();    // dx1
                   c1y = y;                      // dy1
                   c2x = c1x + stack.shift();    // dx2
                   c2y = c1y + stack.shift();    // dy2
                   jpx = c2x + stack.shift();    // dx3
                   jpy = c2y;                    // dy3
                   c3x = jpx + stack.shift();    // dx4
                   c3y = c2y;                    // dy4
                   c4x = c3x + stack.shift();    // dx5
                   c4y = y;                      // dy5
                   x = c4x + stack.shift();      // dx6
                   p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
                   p.curveTo(c3x, c3y, c4x, c4y, x, y);
                   break;
               case 36: // hflex1
                   // |- dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6 hflex1 (12 36) |-
                   c1x = x   + stack.shift();    // dx1
                   c1y = y   + stack.shift();    // dy1
                   c2x = c1x + stack.shift();    // dx2
                   c2y = c1y + stack.shift();    // dy2
                   jpx = c2x + stack.shift();    // dx3
                   jpy = c2y;                    // dy3
                   c3x = jpx + stack.shift();    // dx4
                   c3y = c2y;                    // dy4
                   c4x = c3x + stack.shift();    // dx5
                   c4y = c3y + stack.shift();    // dy5
                   x = c4x + stack.shift();      // dx6
                   p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
                   p.curveTo(c3x, c3y, c4x, c4y, x, y);
                   break;
               case 37: // flex1
                   // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 d6 flex1 (12 37) |-
                   c1x = x   + stack.shift();    // dx1
                   c1y = y   + stack.shift();    // dy1
                   c2x = c1x + stack.shift();    // dx2
                   c2y = c1y + stack.shift();    // dy2
                   jpx = c2x + stack.shift();    // dx3
                   jpy = c2y + stack.shift();    // dy3
                   c3x = jpx + stack.shift();    // dx4
                   c3y = jpy + stack.shift();    // dy4
                   c4x = c3x + stack.shift();    // dx5
                   c4y = c3y + stack.shift();    // dy5
                   if (Math.abs(c4x - x) > Math.abs(c4y - y)) {
                       x = c4x + stack.shift();
                   } else {
                       y = c4y + stack.shift();
                   }
                   p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
                   p.curveTo(c3x, c3y, c4x, c4y, x, y);
                   break;
               default:
                   console.log('Glyph ' + glyph.index + ': unknown operator ' + 1200 + v);
                   stack.length = 0;
               }
               break;
           case 14: // endchar
               if (stack.length > 0 && !haveWidth) {
                   width = stack.shift() + font.nominalWidthX;
                   haveWidth = true;
               }
               if (open) {
                   p.closePath();
                   open = false;
               }
               break;
           case 18: // hstemhm
               parseStems();
               break;
           case 19: // hintmask
           case 20: // cntrmask
               parseStems();
               i += (nStems + 7) >> 3;
               break;
           case 21: // rmoveto
               if (stack.length > 2 && !haveWidth) {
                   width = stack.shift() + font.nominalWidthX;
                   haveWidth = true;
               }
               y += stack.pop();
               x += stack.pop();
               newContour(x, y);
               break;
           case 22: // hmoveto
               if (stack.length > 1 && !haveWidth) {
                   width = stack.shift() + font.nominalWidthX;
                   haveWidth = true;
               }
               x += stack.pop();
               newContour(x, y);
               break;
           case 23: // vstemhm
               parseStems();
               break;
           case 24: // rcurveline
               while (stack.length > 2) {
                   c1x = x + stack.shift();
                   c1y = y + stack.shift();
                   c2x = c1x + stack.shift();
                   c2y = c1y + stack.shift();
                   x = c2x + stack.shift();
                   y = c2y + stack.shift();
                   p.curveTo(c1x, c1y, c2x, c2y, x, y);
               }
               x += stack.shift();
               y += stack.shift();
               p.lineTo(x, y);
               break;
           case 25: // rlinecurve
               while (stack.length > 6) {
                   x += stack.shift();
                   y += stack.shift();
                   p.lineTo(x, y);
               }
               c1x = x + stack.shift();
               c1y = y + stack.shift();
               c2x = c1x + stack.shift();
               c2y = c1y + stack.shift();
               x = c2x + stack.shift();
               y = c2y + stack.shift();
               p.curveTo(c1x, c1y, c2x, c2y, x, y);
               break;
           case 26: // vvcurveto
               if (stack.length % 2) {
                   x += stack.shift();
               }
               while (stack.length > 0) {
                   c1x = x;
                   c1y = y + stack.shift();
                   c2x = c1x + stack.shift();
                   c2y = c1y + stack.shift();
                   x = c2x;
                   y = c2y + stack.shift();
                   p.curveTo(c1x, c1y, c2x, c2y, x, y);
               }
               break;
           case 27: // hhcurveto
               if (stack.length % 2) {
                   y += stack.shift();
               }
               while (stack.length > 0) {
                   c1x = x + stack.shift();
                   c1y = y;
                   c2x = c1x + stack.shift();
                   c2y = c1y + stack.shift();
                   x = c2x + stack.shift();
                   y = c2y;
                   p.curveTo(c1x, c1y, c2x, c2y, x, y);
               }
               break;
           case 28: // shortint
               b1 = code[i];
               b2 = code[i + 1];
               stack.push(((b1 << 24) | (b2 << 16)) >> 16);
               i += 2;
               break;
           case 29: // callgsubr
               codeIndex = stack.pop() + font.gsubrsBias;
               subrCode = font.gsubrs[codeIndex];
               if (subrCode) {
                   parse(subrCode);
               }
               break;
           case 30: // vhcurveto
               while (stack.length > 0) {
                   c1x = x;
                   c1y = y + stack.shift();
                   c2x = c1x + stack.shift();
                   c2y = c1y + stack.shift();
                   x = c2x + stack.shift();
                   y = c2y + (stack.length === 1 ? stack.shift() : 0);
                   p.curveTo(c1x, c1y, c2x, c2y, x, y);
                   if (stack.length === 0) {
                       break;
                   }
                   c1x = x + stack.shift();
                   c1y = y;
                   c2x = c1x + stack.shift();
                   c2y = c1y + stack.shift();
                   y = c2y + stack.shift();
                   x = c2x + (stack.length === 1 ? stack.shift() : 0);
                   p.curveTo(c1x, c1y, c2x, c2y, x, y);
               }
               break;
           case 31: // hvcurveto
               while (stack.length > 0) {
                   c1x = x + stack.shift();
                   c1y = y;
                   c2x = c1x + stack.shift();
                   c2y = c1y + stack.shift();
                   y = c2y + stack.shift();
                   x = c2x + (stack.length === 1 ? stack.shift() : 0);
                   p.curveTo(c1x, c1y, c2x, c2y, x, y);
                   if (stack.length === 0) {
                       break;
                   }
                   c1x = x;
                   c1y = y + stack.shift();
                   c2x = c1x + stack.shift();
                   c2y = c1y + stack.shift();
                   x = c2x + stack.shift();
                   y = c2y + (stack.length === 1 ? stack.shift() : 0);
                   p.curveTo(c1x, c1y, c2x, c2y, x, y);
               }
               break;
           default:
               if (v < 32) {
                   console.log('Glyph ' + glyph.index + ': unknown operator ' + v);
               } else if (v < 247) {
                   stack.push(v - 139);
               } else if (v < 251) {
                   b1 = code[i];
                   i += 1;
                   stack.push((v - 247) * 256 + b1 + 108);
               } else if (v < 255) {
                   b1 = code[i];
                   i += 1;
                   stack.push(-(v - 251) * 256 - b1 - 108);
               } else {
                   b1 = code[i];
                   b2 = code[i + 1];
                   b3 = code[i + 2];
                   b4 = code[i + 3];
                   i += 4;
                   stack.push(((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65536);
               }
           }
       }
   }
   parse(code);
   glyph.advanceWidth = width;
   return p;

}

// Subroutines are encoded using the negative half of the number space. // See type 2 chapter 4.7 "Subroutine operators". function calcCFFSubroutineBias(subrs) {

   var bias;
   if (subrs.length < 1240) {
       bias = 107;
   } else if (subrs.length < 33900) {
       bias = 1131;
   } else {
       bias = 32768;
   }
   return bias;

}

// Parse the `CFF` table, which contains the glyph outlines in PostScript format. function parseCFFTable(data, start, font) {

   font.tables.cff = {};
   var header = parseCFFHeader(data, start);
   var nameIndex = parseCFFIndex(data, header.endOffset, parse.bytesToString);
   var topDictIndex = parseCFFIndex(data, nameIndex.endOffset);
   var stringIndex = parseCFFIndex(data, topDictIndex.endOffset, parse.bytesToString);
   var globalSubrIndex = parseCFFIndex(data, stringIndex.endOffset);
   font.gsubrs = globalSubrIndex.objects;
   font.gsubrsBias = calcCFFSubroutineBias(font.gsubrs);
   var topDictData = new DataView(new Uint8Array(topDictIndex.objects[0]).buffer);
   var topDict = parseCFFTopDict(topDictData, stringIndex.objects);
   font.tables.cff.topDict = topDict;
   var privateDictOffset = start + topDict['private'][1];
   var privateDict = parseCFFPrivateDict(data, privateDictOffset, topDict['private'][0], stringIndex.objects);
   font.defaultWidthX = privateDict.defaultWidthX;
   font.nominalWidthX = privateDict.nominalWidthX;
   if (privateDict.subrs !== 0) {
       var subrOffset = privateDictOffset + privateDict.subrs;
       var subrIndex = parseCFFIndex(data, subrOffset);
       font.subrs = subrIndex.objects;
       font.subrsBias = calcCFFSubroutineBias(font.subrs);
   } else {
       font.subrs = [];
       font.subrsBias = 0;
   }
   // Offsets in the top dict are relative to the beginning of the CFF data, so add the CFF start offset.
   var charStringsIndex = parseCFFIndex(data, start + topDict.charStrings);
   font.nGlyphs = charStringsIndex.objects.length;
   var charset = parseCFFCharset(data, start + topDict.charset, font.nGlyphs, stringIndex.objects);
   if (topDict.encoding === 0) { // Standard encoding
       font.cffEncoding = new encoding.CffEncoding(encoding.cffStandardEncoding, charset);
   } else if (topDict.encoding === 1) { // Expert encoding
       font.cffEncoding = new encoding.CffEncoding(encoding.cffExpertEncoding, charset);
   } else {
       font.cffEncoding = parseCFFEncoding(data, start + topDict.encoding, charset);
   }
   // Prefer the CMAP encoding to the CFF encoding.
   font.encoding = font.encoding || font.cffEncoding;
   font.glyphs = new glyphset.GlyphSet(font);
   for (var i = 0; i < font.nGlyphs; i += 1) {
       var charString = charStringsIndex.objects[i];
       font.glyphs.push(i, glyphset.cffGlyphLoader(font, i, parseCFFCharstring, charString));
   }

}

// Convert a string to a String ID (SID). // The list of strings is modified in place. function encodeString(s, strings) {

   var sid;
   // Is the string in the CFF standard strings?
   var i = encoding.cffStandardStrings.indexOf(s);
   if (i >= 0) {
       sid = i;
   }
   // Is the string already in the string index?
   i = strings.indexOf(s);
   if (i >= 0) {
       sid = i + encoding.cffStandardStrings.length;
   } else {
       sid = encoding.cffStandardStrings.length + strings.length;
       strings.push(s);
   }
   return sid;

}

function makeHeader() {

   return new table.Table('Header', [
       {name: 'major', type: 'Card8', value: 1},
       {name: 'minor', type: 'Card8', value: 0},
       {name: 'hdrSize', type: 'Card8', value: 4},
       {name: 'major', type: 'Card8', value: 1}
   ]);

}

function makeNameIndex(fontNames) {

   var t = new table.Table('Name INDEX', [
       {name: 'names', type: 'INDEX', value: []}
   ]);
   t.names = [];
   for (var i = 0; i < fontNames.length; i += 1) {
       t.names.push({name: 'name_' + i, type: 'NAME', value: fontNames[i]});
   }
   return t;

}

// Given a dictionary's metadata, create a DICT structure. function makeDict(meta, attrs, strings) {

   var m = {};
   for (var i = 0; i < meta.length; i += 1) {
       var entry = meta[i];
       var value = attrs[entry.name];
       if (value !== undefined && !equals(value, entry.value)) {
           if (entry.type === 'SID') {
               value = encodeString(value, strings);
           }
           m[entry.op] = {name: entry.name, type: entry.type, value: value};
       }
   }
   return m;

}

// The Top DICT houses the global font attributes. function makeTopDict(attrs, strings) {

   var t = new table.Table('Top DICT', [
       {name: 'dict', type: 'DICT', value: {}}
   ]);
   t.dict = makeDict(TOP_DICT_META, attrs, strings);
   return t;

}

function makeTopDictIndex(topDict) {

   var t = new table.Table('Top DICT INDEX', [
       {name: 'topDicts', type: 'INDEX', value: []}
   ]);
   t.topDicts = [{name: 'topDict_0', type: 'TABLE', value: topDict}];
   return t;

}

function makeStringIndex(strings) {

   var t = new table.Table('String INDEX', [
       {name: 'strings', type: 'INDEX', value: []}
   ]);
   t.strings = [];
   for (var i = 0; i < strings.length; i += 1) {
       t.strings.push({name: 'string_' + i, type: 'STRING', value: strings[i]});
   }
   return t;

}

function makeGlobalSubrIndex() {

   // Currently we don't use subroutines.
   return new table.Table('Global Subr INDEX', [
       {name: 'subrs', type: 'INDEX', value: []}
   ]);

}

function makeCharsets(glyphNames, strings) {

   var t = new table.Table('Charsets', [
       {name: 'format', type: 'Card8', value: 0}
   ]);
   for (var i = 0; i < glyphNames.length; i += 1) {
       var glyphName = glyphNames[i];
       var glyphSID = encodeString(glyphName, strings);
       t.fields.push({name: 'glyph_' + i, type: 'SID', value: glyphSID});
   }
   return t;

}

function glyphToOps(glyph) {

   var ops = [];
   var path = glyph.path;
   ops.push({name: 'width', type: 'NUMBER', value: glyph.advanceWidth});
   var x = 0;
   var y = 0;
   for (var i = 0; i < path.commands.length; i += 1) {
       var dx;
       var dy;
       var cmd = path.commands[i];
       if (cmd.type === 'Q') {
           // CFF only supports bézier curves, so convert the quad to a bézier.
           var _13 = 1 / 3;
           var _23 = 2 / 3;
           // We're going to create a new command so we don't change the original path.
           cmd = {
               type: 'C',
               x: cmd.x,
               y: cmd.y,
               x1: _13 * x + _23 * cmd.x1,
               y1: _13 * y + _23 * cmd.y1,
               x2: _13 * cmd.x + _23 * cmd.x1,
               y2: _13 * cmd.y + _23 * cmd.y1
           };
       }
       if (cmd.type === 'M') {
           dx = Math.round(cmd.x - x);
           dy = Math.round(cmd.y - y);
           ops.push({name: 'dx', type: 'NUMBER', value: dx});
           ops.push({name: 'dy', type: 'NUMBER', value: dy});
           ops.push({name: 'rmoveto', type: 'OP', value: 21});
           x = Math.round(cmd.x);
           y = Math.round(cmd.y);
       } else if (cmd.type === 'L') {
           dx = Math.round(cmd.x - x);
           dy = Math.round(cmd.y - y);
           ops.push({name: 'dx', type: 'NUMBER', value: dx});
           ops.push({name: 'dy', type: 'NUMBER', value: dy});
           ops.push({name: 'rlineto', type: 'OP', value: 5});
           x = Math.round(cmd.x);
           y = Math.round(cmd.y);
       } else if (cmd.type === 'C') {
           var dx1 = Math.round(cmd.x1 - x);
           var dy1 = Math.round(cmd.y1 - y);
           var dx2 = Math.round(cmd.x2 - cmd.x1);
           var dy2 = Math.round(cmd.y2 - cmd.y1);
           dx = Math.round(cmd.x - cmd.x2);
           dy = Math.round(cmd.y - cmd.y2);
           ops.push({name: 'dx1', type: 'NUMBER', value: dx1});
           ops.push({name: 'dy1', type: 'NUMBER', value: dy1});
           ops.push({name: 'dx2', type: 'NUMBER', value: dx2});
           ops.push({name: 'dy2', type: 'NUMBER', value: dy2});
           ops.push({name: 'dx', type: 'NUMBER', value: dx});
           ops.push({name: 'dy', type: 'NUMBER', value: dy});
           ops.push({name: 'rrcurveto', type: 'OP', value: 8});
           x = Math.round(cmd.x);
           y = Math.round(cmd.y);
       }
       // Contours are closed automatically.
   }
   ops.push({name: 'endchar', type: 'OP', value: 14});
   return ops;

}

function makeCharStringsIndex(glyphs) {

   var t = new table.Table('CharStrings INDEX', [
       {name: 'charStrings', type: 'INDEX', value: []}
   ]);
   for (var i = 0; i < glyphs.length; i += 1) {
       var glyph = glyphs.get(i);
       var ops = glyphToOps(glyph);
       t.charStrings.push({name: glyph.name, type: 'CHARSTRING', value: ops});
   }
   return t;

}

function makePrivateDict(attrs, strings) {

   var t = new table.Table('Private DICT', [
       {name: 'dict', type: 'DICT', value: {}}
   ]);
   t.dict = makeDict(PRIVATE_DICT_META, attrs, strings);
   return t;

}

function makePrivateDictIndex(privateDict) {

   var t = new table.Table('Private DICT INDEX', [
       {name: 'privateDicts', type: 'INDEX', value: []}
   ]);
   t.privateDicts = [{name: 'privateDict_0', type: 'TABLE', value: privateDict}];
   return t;

}

function makeCFFTable(glyphs, options) {

   var t = new table.Table('CFF ', [
       {name: 'header', type: 'TABLE'},
       {name: 'nameIndex', type: 'TABLE'},
       {name: 'topDictIndex', type: 'TABLE'},
       {name: 'stringIndex', type: 'TABLE'},
       {name: 'globalSubrIndex', type: 'TABLE'},
       {name: 'charsets', type: 'TABLE'},
       {name: 'charStringsIndex', type: 'TABLE'},
       {name: 'privateDictIndex', type: 'TABLE'}
   ]);
   var fontScale = 1 / options.unitsPerEm;
   // We use non-zero values for the offsets so that the DICT encodes them.
   // This is important because the size of the Top DICT plays a role in offset calculation,
   // and the size shouldn't change after we've written correct offsets.
   var attrs = {
       version: options.version,
       fullName: options.fullName,
       familyName: options.familyName,
       weight: options.weightName,
       fontMatrix: [fontScale, 0, 0, fontScale, 0, 0],
       charset: 999,
       encoding: 0,
       charStrings: 999,
       private: [0, 999]
   };
   var privateAttrs = {};
   var glyphNames = [];
   var glyph;
   // Skip first glyph (.notdef)
   for (var i = 1; i < glyphs.length; i += 1) {
       glyph = glyphs.get(i);
       glyphNames.push(glyph.name);
   }
   var strings = [];
   t.header = makeHeader();
   t.nameIndex = makeNameIndex([options.postScriptName]);
   var topDict = makeTopDict(attrs, strings);
   t.topDictIndex = makeTopDictIndex(topDict);
   t.globalSubrIndex = makeGlobalSubrIndex();
   t.charsets = makeCharsets(glyphNames, strings);
   t.charStringsIndex = makeCharStringsIndex(glyphs);
   var privateDict = makePrivateDict(privateAttrs, strings);
   t.privateDictIndex = makePrivateDictIndex(privateDict);
   // Needs to come at the end, to encode all custom strings used in the font.
   t.stringIndex = makeStringIndex(strings);
   var startOffset = t.header.sizeOf() +
       t.nameIndex.sizeOf() +
       t.topDictIndex.sizeOf() +
       t.stringIndex.sizeOf() +
       t.globalSubrIndex.sizeOf();
   attrs.charset = startOffset;
   // We use the CFF standard encoding; proper encoding will be handled in cmap.
   attrs.encoding = 0;
   attrs.charStrings = attrs.charset + t.charsets.sizeOf();
   attrs.private[1] = attrs.charStrings + t.charStringsIndex.sizeOf();
   // Recreate the Top DICT INDEX with the correct offsets.
   topDict = makeTopDict(attrs, strings);
   t.topDictIndex = makeTopDictIndex(topDict);
   return t;

}

exports.parse = parseCFFTable; exports.make = makeCFFTable;

},{"../encoding":4,"../glyphset":7,"../parse":9,"../path":10,"../table":11}],13:[function(_dereq_,module,exports){ // The `cmap` table stores the mappings from characters to glyphs. // https://www.microsoft.com/typography/OTSPEC/cmap.htm

'use strict';

var check = _dereq_('../check'); var parse = _dereq_('../parse'); var table = _dereq_('../table');

// Parse the `cmap` table. This table stores the mappings from characters to glyphs. // There are many available formats, but we only support the Windows format 4. // This function returns a `CmapEncoding` object or null if no supported format could be found. function parseCmapTable(data, start) {

   var i;
   var cmap = {};
   cmap.version = parse.getUShort(data, start);
   check.argument(cmap.version === 0, 'cmap table version should be 0.');
   // The cmap table can contain many sub-tables, each with their own format.
   // We're only interested in a "platform 3" table. This is a Windows format.
   cmap.numTables = parse.getUShort(data, start + 2);
   var offset = -1;
   for (i = 0; i < cmap.numTables; i += 1) {
       var platformId = parse.getUShort(data, start + 4 + (i * 8));
       var encodingId = parse.getUShort(data, start + 4 + (i * 8) + 2);
       if (platformId === 3 && (encodingId === 1 || encodingId === 0)) {
           offset = parse.getULong(data, start + 4 + (i * 8) + 4);
           break;
       }
   }
   if (offset === -1) {
       // There is no cmap table in the font that we support, so return null.
       // This font will be marked as unsupported.
       return null;
   }
   var p = new parse.Parser(data, start + offset);
   cmap.format = p.parseUShort();
   check.argument(cmap.format === 4, 'Only format 4 cmap tables are supported.');
   // Length in bytes of the sub-tables.
   cmap.length = p.parseUShort();
   cmap.language = p.parseUShort();
   // segCount is stored x 2.
   var segCount;
   cmap.segCount = segCount = p.parseUShort() >> 1;
   // Skip searchRange, entrySelector, rangeShift.
   p.skip('uShort', 3);
   // The "unrolled" mapping from character codes to glyph indices.
   cmap.glyphIndexMap = {};
   var endCountParser = new parse.Parser(data, start + offset + 14);
   var startCountParser = new parse.Parser(data, start + offset + 16 + segCount * 2);
   var idDeltaParser = new parse.Parser(data, start + offset + 16 + segCount * 4);
   var idRangeOffsetParser = new parse.Parser(data, start + offset + 16 + segCount * 6);
   var glyphIndexOffset = start + offset + 16 + segCount * 8;
   for (i = 0; i < segCount - 1; i += 1) {
       var glyphIndex;
       var endCount = endCountParser.parseUShort();
       var startCount = startCountParser.parseUShort();
       var idDelta = idDeltaParser.parseShort();
       var idRangeOffset = idRangeOffsetParser.parseUShort();
       for (var c = startCount; c <= endCount; c += 1) {
           if (idRangeOffset !== 0) {
               // The idRangeOffset is relative to the current position in the idRangeOffset array.
               // Take the current offset in the idRangeOffset array.
               glyphIndexOffset = (idRangeOffsetParser.offset + idRangeOffsetParser.relativeOffset - 2);
               // Add the value of the idRangeOffset, which will move us into the glyphIndex array.
               glyphIndexOffset += idRangeOffset;
               // Then add the character index of the current segment, multiplied by 2 for USHORTs.
               glyphIndexOffset += (c - startCount) * 2;
               glyphIndex = parse.getUShort(data, glyphIndexOffset);
               if (glyphIndex !== 0) {
                   glyphIndex = (glyphIndex + idDelta) & 0xFFFF;
               }
           } else {
               glyphIndex = (c + idDelta) & 0xFFFF;
           }
           cmap.glyphIndexMap[c] = glyphIndex;
       }
   }
   return cmap;

}

function addSegment(t, code, glyphIndex) {

   t.segments.push({
       end: code,
       start: code,
       delta: -(code - glyphIndex),
       offset: 0
   });

}

function addTerminatorSegment(t) {

   t.segments.push({
       end: 0xFFFF,
       start: 0xFFFF,
       delta: 1,
       offset: 0
   });

}

function makeCmapTable(glyphs) {

   var i;
   var t = new table.Table('cmap', [
       {name: 'version', type: 'USHORT', value: 0},
       {name: 'numTables', type: 'USHORT', value: 1},
       {name: 'platformID', type: 'USHORT', value: 3},
       {name: 'encodingID', type: 'USHORT', value: 1},
       {name: 'offset', type: 'ULONG', value: 12},
       {name: 'format', type: 'USHORT', value: 4},
       {name: 'length', type: 'USHORT', value: 0},
       {name: 'language', type: 'USHORT', value: 0},
       {name: 'segCountX2', type: 'USHORT', value: 0},
       {name: 'searchRange', type: 'USHORT', value: 0},
       {name: 'entrySelector', type: 'USHORT', value: 0},
       {name: 'rangeShift', type: 'USHORT', value: 0}
   ]);
   t.segments = [];
   for (i = 0; i < glyphs.length; i += 1) {
       var glyph = glyphs.get(i);
       for (var j = 0; j < glyph.unicodes.length; j += 1) {
           addSegment(t, glyph.unicodes[j], i);
       }
       t.segments = t.segments.sort(function(a, b) {
           return a.start - b.start;
       });
   }
   addTerminatorSegment(t);
   var segCount;
   segCount = t.segments.length;
   t.segCountX2 = segCount * 2;
   t.searchRange = Math.pow(2, Math.floor(Math.log(segCount) / Math.log(2))) * 2;
   t.entrySelector = Math.log(t.searchRange / 2) / Math.log(2);
   t.rangeShift = t.segCountX2 - t.searchRange;
   // Set up parallel segment arrays.
   var endCounts = [];
   var startCounts = [];
   var idDeltas = [];
   var idRangeOffsets = [];
   var glyphIds = [];
   for (i = 0; i < segCount; i += 1) {
       var segment = t.segments[i];
       endCounts = endCounts.concat({name: 'end_' + i, type: 'USHORT', value: segment.end});
       startCounts = startCounts.concat({name: 'start_' + i, type: 'USHORT', value: segment.start});
       idDeltas = idDeltas.concat({name: 'idDelta_' + i, type: 'SHORT', value: segment.delta});
       idRangeOffsets = idRangeOffsets.concat({name: 'idRangeOffset_' + i, type: 'USHORT', value: segment.offset});
       if (segment.glyphId !== undefined) {
           glyphIds = glyphIds.concat({name: 'glyph_' + i, type: 'USHORT', value: segment.glyphId});
       }
   }
   t.fields = t.fields.concat(endCounts);
   t.fields.push({name: 'reservedPad', type: 'USHORT', value: 0});
   t.fields = t.fields.concat(startCounts);
   t.fields = t.fields.concat(idDeltas);
   t.fields = t.fields.concat(idRangeOffsets);
   t.fields = t.fields.concat(glyphIds);
   t.length = 14 + // Subtable header
       endCounts.length * 2 +
       2 + // reservedPad
       startCounts.length * 2 +
       idDeltas.length * 2 +
       idRangeOffsets.length * 2 +
       glyphIds.length * 2;
   return t;

}

exports.parse = parseCmapTable; exports.make = makeCmapTable;

},{"../check":2,"../parse":9,"../table":11}],14:[function(_dereq_,module,exports){ // The `glyf` table describes the glyphs in TrueType outline format. // http://www.microsoft.com/typography/otspec/glyf.htm

'use strict';

var check = _dereq_('../check'); var glyphset = _dereq_('../glyphset'); var parse = _dereq_('../parse'); var path = _dereq_('../path');

// Parse the coordinate data for a glyph. function parseGlyphCoordinate(p, flag, previousValue, shortVectorBitMask, sameBitMask) {

   var v;
   if ((flag & shortVectorBitMask) > 0) {
       // The coordinate is 1 byte long.
       v = p.parseByte();
       // The `same` bit is re-used for short values to signify the sign of the value.
       if ((flag & sameBitMask) === 0) {
           v = -v;
       }
       v = previousValue + v;
   } else {
       //  The coordinate is 2 bytes long.
       // If the `same` bit is set, the coordinate is the same as the previous coordinate.
       if ((flag & sameBitMask) > 0) {
           v = previousValue;
       } else {
           // Parse the coordinate as a signed 16-bit delta value.
           v = previousValue + p.parseShort();
       }
   }
   return v;

}

// Parse a TrueType glyph. function parseGlyph(glyph, data, start) {

   var p = new parse.Parser(data, start);
   glyph.numberOfContours = p.parseShort();
   glyph.xMin = p.parseShort();
   glyph.yMin = p.parseShort();
   glyph.xMax = p.parseShort();
   glyph.yMax = p.parseShort();
   var flags;
   var flag;
   if (glyph.numberOfContours > 0) {
       var i;
       // This glyph is not a composite.
       var endPointIndices = glyph.endPointIndices = [];
       for (i = 0; i < glyph.numberOfContours; i += 1) {
           endPointIndices.push(p.parseUShort());
       }
       glyph.instructionLength = p.parseUShort();
       glyph.instructions = [];
       for (i = 0; i < glyph.instructionLength; i += 1) {
           glyph.instructions.push(p.parseByte());
       }
       var numberOfCoordinates = endPointIndices[endPointIndices.length - 1] + 1;
       flags = [];
       for (i = 0; i < numberOfCoordinates; i += 1) {
           flag = p.parseByte();
           flags.push(flag);
           // If bit 3 is set, we repeat this flag n times, where n is the next byte.
           if ((flag & 8) > 0) {
               var repeatCount = p.parseByte();
               for (var j = 0; j < repeatCount; j += 1) {
                   flags.push(flag);
                   i += 1;
               }
           }
       }
       check.argument(flags.length === numberOfCoordinates, 'Bad flags.');
       if (endPointIndices.length > 0) {
           var points = [];
           var point;
           // X/Y coordinates are relative to the previous point, except for the first point which is relative to 0,0.
           if (numberOfCoordinates > 0) {
               for (i = 0; i < numberOfCoordinates; i += 1) {
                   flag = flags[i];
                   point = {};
                   point.onCurve = !!(flag & 1);
                   point.lastPointOfContour = endPointIndices.indexOf(i) >= 0;
                   points.push(point);
               }
               var px = 0;
               for (i = 0; i < numberOfCoordinates; i += 1) {
                   flag = flags[i];
                   point = points[i];
                   point.x = parseGlyphCoordinate(p, flag, px, 2, 16);
                   px = point.x;
               }
               var py = 0;
               for (i = 0; i < numberOfCoordinates; i += 1) {
                   flag = flags[i];
                   point = points[i];
                   point.y = parseGlyphCoordinate(p, flag, py, 4, 32);
                   py = point.y;
               }
           }
           glyph.points = points;
       } else {
           glyph.points = [];
       }
   } else if (glyph.numberOfContours === 0) {
       glyph.points = [];
   } else {
       glyph.isComposite = true;
       glyph.points = [];
       glyph.components = [];
       var moreComponents = true;
       while (moreComponents) {
           flags = p.parseUShort();
           var component = {
               glyphIndex: p.parseUShort(),
               xScale: 1,
               scale01: 0,
               scale10: 0,
               yScale: 1,
               dx: 0,
               dy: 0
           };
           if ((flags & 1) > 0) {
               // The arguments are words
               component.dx = p.parseShort();
               component.dy = p.parseShort();
           } else {
               // The arguments are bytes
               component.dx = p.parseChar();
               component.dy = p.parseChar();
           }
           if ((flags & 8) > 0) {
               // We have a scale
               component.xScale = component.yScale = p.parseF2Dot14();
           } else if ((flags & 64) > 0) {
               // We have an X / Y scale
               component.xScale = p.parseF2Dot14();
               component.yScale = p.parseF2Dot14();
           } else if ((flags & 128) > 0) {
               // We have a 2x2 transformation
               component.xScale = p.parseF2Dot14();
               component.scale01 = p.parseF2Dot14();
               component.scale10 = p.parseF2Dot14();
               component.yScale = p.parseF2Dot14();
           }
           glyph.components.push(component);
           moreComponents = !!(flags & 32);
       }
   }

}

// Transform an array of points and return a new array. function transformPoints(points, transform) {

   var newPoints = [];
   for (var i = 0; i < points.length; i += 1) {
       var pt = points[i];
       var newPt = {
           x: transform.xScale * pt.x + transform.scale01 * pt.y + transform.dx,
           y: transform.scale10 * pt.x + transform.yScale * pt.y + transform.dy,
           onCurve: pt.onCurve,
           lastPointOfContour: pt.lastPointOfContour
       };
       newPoints.push(newPt);
   }
   return newPoints;

}

function getContours(points) {

   var contours = [];
   var currentContour = [];
   for (var i = 0; i < points.length; i += 1) {
       var pt = points[i];
       currentContour.push(pt);
       if (pt.lastPointOfContour) {
           contours.push(currentContour);
           currentContour = [];
       }
   }
   check.argument(currentContour.length === 0, 'There are still points left in the current contour.');
   return contours;

}

// Convert the TrueType glyph outline to a Path. function getPath(points) {

   var p = new path.Path();
   if (!points) {
       return p;
   }
   var contours = getContours(points);
   for (var i = 0; i < contours.length; i += 1) {
       var contour = contours[i];
       var firstPt = contour[0];
       var lastPt = contour[contour.length - 1];
       var curvePt;
       var realFirstPoint;
       if (firstPt.onCurve) {
           curvePt = null;
           // The first point will be consumed by the moveTo command,
           // so skip it in the loop.
           realFirstPoint = true;
       } else {
           if (lastPt.onCurve) {
               // If the first point is off-curve and the last point is on-curve,
               // start at the last point.
               firstPt = lastPt;
           } else {
               // If both first and last points are off-curve, start at their middle.
               firstPt = { x: (firstPt.x + lastPt.x) / 2, y: (firstPt.y + lastPt.y) / 2 };
           }
           curvePt = firstPt;
           // The first point is synthesized, so don't skip the real first point.
           realFirstPoint = false;
       }
       p.moveTo(firstPt.x, firstPt.y);
       for (var j = realFirstPoint ? 1 : 0; j < contour.length; j += 1) {
           var pt = contour[j];
           var prevPt = j === 0 ? firstPt : contour[j - 1];
           if (prevPt.onCurve && pt.onCurve) {
               // This is a straight line.
               p.lineTo(pt.x, pt.y);
           } else if (prevPt.onCurve && !pt.onCurve) {
               curvePt = pt;
           } else if (!prevPt.onCurve && !pt.onCurve) {
               var midPt = { x: (prevPt.x + pt.x) / 2, y: (prevPt.y + pt.y) / 2 };
               p.quadraticCurveTo(prevPt.x, prevPt.y, midPt.x, midPt.y);
               curvePt = pt;
           } else if (!prevPt.onCurve && pt.onCurve) {
               // Previous point off-curve, this point on-curve.
               p.quadraticCurveTo(curvePt.x, curvePt.y, pt.x, pt.y);
               curvePt = null;
           } else {
               throw new Error('Invalid state.');
           }
       }
       if (firstPt !== lastPt) {
           // Connect the last and first points
           if (curvePt) {
               p.quadraticCurveTo(curvePt.x, curvePt.y, firstPt.x, firstPt.y);
           } else {
               p.lineTo(firstPt.x, firstPt.y);
           }
       }
   }
   p.closePath();
   return p;

}

function buildPath(glyphs, glyph) {

   if (glyph.isComposite) {
       for (var j = 0; j < glyph.components.length; j += 1) {
           var component = glyph.components[j];
           var componentGlyph = glyphs.get(component.glyphIndex);
           if (componentGlyph.points) {
               var transformedPoints = transformPoints(componentGlyph.points, component);
               glyph.points = glyph.points.concat(transformedPoints);
           }
       }
   }
   return getPath(glyph.points);

}

// Parse all the glyphs according to the offsets from the `loca` table. function parseGlyfTable(data, start, loca, font) {

   var glyphs = new glyphset.GlyphSet(font);
   var i;
   // The last element of the loca table is invalid.
   for (i = 0; i < loca.length - 1; i += 1) {
       var offset = loca[i];
       var nextOffset = loca[i + 1];
       if (offset !== nextOffset) {
           glyphs.push(i, glyphset.ttfGlyphLoader(font, i, parseGlyph, data, start + offset, buildPath));
       } else {
           glyphs.push(i, glyphset.glyphLoader(font, i));
       }
   }
   return glyphs;

}

exports.parse = parseGlyfTable;

},{"../check":2,"../glyphset":7,"../parse":9,"../path":10}],15:[function(_dereq_,module,exports){ // The `GPOS` table contains kerning pairs, among other things. // https://www.microsoft.com/typography/OTSPEC/gpos.htm

'use strict';

var check = _dereq_('../check'); var parse = _dereq_('../parse');

// Parse ScriptList and FeatureList tables of GPOS, GSUB, GDEF, BASE, JSTF tables. // These lists are unused by now, this function is just the basis for a real parsing. function parseTaggedListTable(data, start) {

   var p = new parse.Parser(data, start);
   var n = p.parseUShort();
   var list = [];
   for (var i = 0; i < n; i++) {
       list[p.parseTag()] = { offset: p.parseUShort() };
   }
   return list;

}

// Parse a coverage table in a GSUB, GPOS or GDEF table. // Format 1 is a simple list of glyph ids, // Format 2 is a list of ranges. It is expanded in a list of glyphs, maybe not the best idea. function parseCoverageTable(data, start) {

   var p = new parse.Parser(data, start);
   var format = p.parseUShort();
   var count =  p.parseUShort();
   if (format === 1) {
       return p.parseUShortList(count);
   }
   else if (format === 2) {
       var coverage = [];
       for (; count--;) {
           var begin = p.parseUShort();
           var end = p.parseUShort();
           var index = p.parseUShort();
           for (var i = begin; i <= end; i++) {
               coverage[index++] = i;
           }
       }
       return coverage;
   }

}

// Parse a Class Definition Table in a GSUB, GPOS or GDEF table. // Returns a function that gets a class value from a glyph ID. function parseClassDefTable(data, start) {

   var p = new parse.Parser(data, start);
   var format = p.parseUShort();
   if (format === 1) {
       // Format 1 specifies a range of consecutive glyph indices, one class per glyph ID.
       var startGlyph = p.parseUShort();
       var glyphCount = p.parseUShort();
       var classes = p.parseUShortList(glyphCount);
       return function(glyphID) {
           return classes[glyphID - startGlyph] || 0;
       };
   }
   else if (format === 2) {
       // Format 2 defines multiple groups of glyph indices that belong to the same class.
       var rangeCount = p.parseUShort();
       var startGlyphs = [];
       var endGlyphs = [];
       var classValues = [];
       for (var i = 0; i < rangeCount; i++) {
           startGlyphs[i] = p.parseUShort();
           endGlyphs[i] = p.parseUShort();
           classValues[i] = p.parseUShort();
       }
       return function(glyphID) {
           var l = 0;
           var r = startGlyphs.length - 1;
           while (l < r) {
               var c = (l + r + 1) >> 1;
               if (glyphID < startGlyphs[c]) {
                   r = c - 1;
               } else {
                   l = c;
               }
           }
           if (startGlyphs[l] <= glyphID && glyphID <= endGlyphs[l]) {
               return classValues[l] || 0;
           }
           return 0;
       };
   }

}

// Parse a pair adjustment positioning subtable, format 1 or format 2 // The subtable is returned in the form of a lookup function. function parsePairPosSubTable(data, start) {

   var p = new parse.Parser(data, start);
   // This part is common to format 1 and format 2 subtables
   var format = p.parseUShort();
   var coverageOffset = p.parseUShort();
   var coverage = parseCoverageTable(data, start + coverageOffset);
   // valueFormat 4: XAdvance only, 1: XPlacement only, 0: no ValueRecord for second glyph
   // Only valueFormat1=4 and valueFormat2=0 is supported.
   var valueFormat1 = p.parseUShort();
   var valueFormat2 = p.parseUShort();
   var value1;
   var value2;
   if (valueFormat1 !== 4 || valueFormat2 !== 0) return;
   var sharedPairSets = {};
   if (format === 1) {
       // Pair Positioning Adjustment: Format 1
       var pairSetCount = p.parseUShort();
       var pairSet = [];
       // Array of offsets to PairSet tables-from beginning of PairPos subtable-ordered by Coverage Index
       var pairSetOffsets = p.parseOffset16List(pairSetCount);
       for (var firstGlyph = 0; firstGlyph < pairSetCount; firstGlyph++) {
           var pairSetOffset = pairSetOffsets[firstGlyph];
           var sharedPairSet = sharedPairSets[pairSetOffset];
           if (!sharedPairSet) {
               // Parse a pairset table in a pair adjustment subtable format 1
               sharedPairSet = {};
               p.relativeOffset = pairSetOffset;
               var pairValueCount = p.parseUShort();
               for (; pairValueCount--;) {
                   var secondGlyph = p.parseUShort();
                   if (valueFormat1) value1 = p.parseShort();
                   if (valueFormat2) value2 = p.parseShort();
                   // We only support valueFormat1 = 4 and valueFormat2 = 0,
                   // so value1 is the XAdvance and value2 is empty.
                   sharedPairSet[secondGlyph] = value1;
               }
           }
           pairSet[coverage[firstGlyph]] = sharedPairSet;
       }
       return function(leftGlyph, rightGlyph) {
           var pairs = pairSet[leftGlyph];
           if (pairs) return pairs[rightGlyph];
       };
   }
   else if (format === 2) {
       // Pair Positioning Adjustment: Format 2
       var classDef1Offset = p.parseUShort();
       var classDef2Offset = p.parseUShort();
       var class1Count = p.parseUShort();
       var class2Count = p.parseUShort();
       var getClass1 = parseClassDefTable(data, start + classDef1Offset);
       var getClass2 = parseClassDefTable(data, start + classDef2Offset);
       // Parse kerning values by class pair.
       var kerningMatrix = [];
       for (var i = 0; i < class1Count; i++) {
           var kerningRow = kerningMatrix[i] = [];
           for (var j = 0; j < class2Count; j++) {
               if (valueFormat1) value1 = p.parseShort();
               if (valueFormat2) value2 = p.parseShort();
               // We only support valueFormat1 = 4 and valueFormat2 = 0,
               // so value1 is the XAdvance and value2 is empty.
               kerningRow[j] = value1;
           }
       }
       // Convert coverage list to a hash
       var covered = {};
       for (i = 0; i < coverage.length; i++) covered[coverage[i]] = 1;
       // Get the kerning value for a specific glyph pair.
       return function(leftGlyph, rightGlyph) {
           if (!covered[leftGlyph]) return;
           var class1 = getClass1(leftGlyph);
           var class2 = getClass2(rightGlyph);
           var kerningRow = kerningMatrix[class1];
           if (kerningRow) {
               return kerningRow[class2];
           }
       };
   }

}

// Parse a LookupTable (present in of GPOS, GSUB, GDEF, BASE, JSTF tables). function parseLookupTable(data, start) {

   var p = new parse.Parser(data, start);
   var lookupType = p.parseUShort();
   var lookupFlag = p.parseUShort();
   var useMarkFilteringSet = lookupFlag & 0x10;
   var subTableCount = p.parseUShort();
   var subTableOffsets = p.parseOffset16List(subTableCount);
   var table = {
       lookupType: lookupType,
       lookupFlag: lookupFlag,
       markFilteringSet: useMarkFilteringSet ? p.parseUShort() : -1
   };
   // LookupType 2, Pair adjustment
   if (lookupType === 2) {
       var subtables = [];
       for (var i = 0; i < subTableCount; i++) {
           subtables.push(parsePairPosSubTable(data, start + subTableOffsets[i]));
       }
       // Return a function which finds the kerning values in the subtables.
       table.getKerningValue = function(leftGlyph, rightGlyph) {
           for (var i = subtables.length; i--;) {
               var value = subtables[i](leftGlyph, rightGlyph);
               if (value !== undefined) return value;
           }
           return 0;
       };
   }
   return table;

}

// Parse the `GPOS` table which contains, among other things, kerning pairs. // https://www.microsoft.com/typography/OTSPEC/gpos.htm function parseGposTable(data, start, font) {

   var p = new parse.Parser(data, start);
   var tableVersion = p.parseFixed();
   check.argument(tableVersion === 1, 'Unsupported GPOS table version.');
   // ScriptList and FeatureList - ignored for now
   parseTaggedListTable(data, start + p.parseUShort());
   // 'kern' is the feature we are looking for.
   parseTaggedListTable(data, start + p.parseUShort());
   // LookupList
   var lookupListOffset = p.parseUShort();
   p.relativeOffset = lookupListOffset;
   var lookupCount = p.parseUShort();
   var lookupTableOffsets = p.parseOffset16List(lookupCount);
   var lookupListAbsoluteOffset = start + lookupListOffset;
   for (var i = 0; i < lookupCount; i++) {
       var table = parseLookupTable(data, lookupListAbsoluteOffset + lookupTableOffsets[i]);
       if (table.lookupType === 2 && !font.getGposKerningValue) font.getGposKerningValue = table.getKerningValue;
   }

}

exports.parse = parseGposTable;

},{"../check":2,"../parse":9}],16:[function(_dereq_,module,exports){ // The `head` table contains global information about the font. // https://www.microsoft.com/typography/OTSPEC/head.htm

'use strict';

var check = _dereq_('../check'); var parse = _dereq_('../parse'); var table = _dereq_('../table');

// Parse the header `head` table function parseHeadTable(data, start) {

   var head = {};
   var p = new parse.Parser(data, start);
   head.version = p.parseVersion();
   head.fontRevision = Math.round(p.parseFixed() * 1000) / 1000;
   head.checkSumAdjustment = p.parseULong();
   head.magicNumber = p.parseULong();
   check.argument(head.magicNumber === 0x5F0F3CF5, 'Font header has wrong magic number.');
   head.flags = p.parseUShort();
   head.unitsPerEm = p.parseUShort();
   head.created = p.parseLongDateTime();
   head.modified = p.parseLongDateTime();
   head.xMin = p.parseShort();
   head.yMin = p.parseShort();
   head.xMax = p.parseShort();
   head.yMax = p.parseShort();
   head.macStyle = p.parseUShort();
   head.lowestRecPPEM = p.parseUShort();
   head.fontDirectionHint = p.parseShort();
   head.indexToLocFormat = p.parseShort();     // 50
   head.glyphDataFormat = p.parseShort();
   return head;

}

function makeHeadTable(options) {

   return new table.Table('head', [
       {name: 'version', type: 'FIXED', value: 0x00010000},
       {name: 'fontRevision', type: 'FIXED', value: 0x00010000},
       {name: 'checkSumAdjustment', type: 'ULONG', value: 0},
       {name: 'magicNumber', type: 'ULONG', value: 0x5F0F3CF5},
       {name: 'flags', type: 'USHORT', value: 0},
       {name: 'unitsPerEm', type: 'USHORT', value: 1000},
       {name: 'created', type: 'LONGDATETIME', value: 0},
       {name: 'modified', type: 'LONGDATETIME', value: 0},
       {name: 'xMin', type: 'SHORT', value: 0},
       {name: 'yMin', type: 'SHORT', value: 0},
       {name: 'xMax', type: 'SHORT', value: 0},
       {name: 'yMax', type: 'SHORT', value: 0},
       {name: 'macStyle', type: 'USHORT', value: 0},
       {name: 'lowestRecPPEM', type: 'USHORT', value: 0},
       {name: 'fontDirectionHint', type: 'SHORT', value: 2},
       {name: 'indexToLocFormat', type: 'SHORT', value: 0},
       {name: 'glyphDataFormat', type: 'SHORT', value: 0}
   ], options);

}

exports.parse = parseHeadTable; exports.make = makeHeadTable;

},{"../check":2,"../parse":9,"../table":11}],17:[function(_dereq_,module,exports){ // The `hhea` table contains information for horizontal layout. // https://www.microsoft.com/typography/OTSPEC/hhea.htm

'use strict';

var parse = _dereq_('../parse'); var table = _dereq_('../table');

// Parse the horizontal header `hhea` table function parseHheaTable(data, start) {

   var hhea = {};
   var p = new parse.Parser(data, start);
   hhea.version = p.parseVersion();
   hhea.ascender = p.parseShort();
   hhea.descender = p.parseShort();
   hhea.lineGap = p.parseShort();
   hhea.advanceWidthMax = p.parseUShort();
   hhea.minLeftSideBearing = p.parseShort();
   hhea.minRightSideBearing = p.parseShort();
   hhea.xMaxExtent = p.parseShort();
   hhea.caretSlopeRise = p.parseShort();
   hhea.caretSlopeRun = p.parseShort();
   hhea.caretOffset = p.parseShort();
   p.relativeOffset += 8;
   hhea.metricDataFormat = p.parseShort();
   hhea.numberOfHMetrics = p.parseUShort();
   return hhea;

}

function makeHheaTable(options) {

   return new table.Table('hhea', [
       {name: 'version', type: 'FIXED', value: 0x00010000},
       {name: 'ascender', type: 'FWORD', value: 0},
       {name: 'descender', type: 'FWORD', value: 0},
       {name: 'lineGap', type: 'FWORD', value: 0},
       {name: 'advanceWidthMax', type: 'UFWORD', value: 0},
       {name: 'minLeftSideBearing', type: 'FWORD', value: 0},
       {name: 'minRightSideBearing', type: 'FWORD', value: 0},
       {name: 'xMaxExtent', type: 'FWORD', value: 0},
       {name: 'caretSlopeRise', type: 'SHORT', value: 1},
       {name: 'caretSlopeRun', type: 'SHORT', value: 0},
       {name: 'caretOffset', type: 'SHORT', value: 0},
       {name: 'reserved1', type: 'SHORT', value: 0},
       {name: 'reserved2', type: 'SHORT', value: 0},
       {name: 'reserved3', type: 'SHORT', value: 0},
       {name: 'reserved4', type: 'SHORT', value: 0},
       {name: 'metricDataFormat', type: 'SHORT', value: 0},
       {name: 'numberOfHMetrics', type: 'USHORT', value: 0}
   ], options);

}

exports.parse = parseHheaTable; exports.make = makeHheaTable;

},{"../parse":9,"../table":11}],18:[function(_dereq_,module,exports){ // The `hmtx` table contains the horizontal metrics for all glyphs. // https://www.microsoft.com/typography/OTSPEC/hmtx.htm

'use strict';

var parse = _dereq_('../parse'); var table = _dereq_('../table');

// Parse the `hmtx` table, which contains the horizontal metrics for all glyphs. // This function augments the glyph array, adding the advanceWidth and leftSideBearing to each glyph. function parseHmtxTable(data, start, numMetrics, numGlyphs, glyphs) {

   var advanceWidth;
   var leftSideBearing;
   var p = new parse.Parser(data, start);
   for (var i = 0; i < numGlyphs; i += 1) {
       // If the font is monospaced, only one entry is needed. This last entry applies to all subsequent glyphs.
       if (i < numMetrics) {
           advanceWidth = p.parseUShort();
           leftSideBearing = p.parseShort();
       }
       var glyph = glyphs.get(i);
       glyph.advanceWidth = advanceWidth;
       glyph.leftSideBearing = leftSideBearing;
   }

}

function makeHmtxTable(glyphs) {

   var t = new table.Table('hmtx', []);
   for (var i = 0; i < glyphs.length; i += 1) {
       var glyph = glyphs.get(i);
       var advanceWidth = glyph.advanceWidth || 0;
       var leftSideBearing = glyph.leftSideBearing || 0;
       t.fields.push({name: 'advanceWidth_' + i, type: 'USHORT', value: advanceWidth});
       t.fields.push({name: 'leftSideBearing_' + i, type: 'SHORT', value: leftSideBearing});
   }
   return t;

}

exports.parse = parseHmtxTable; exports.make = makeHmtxTable;

},{"../parse":9,"../table":11}],19:[function(_dereq_,module,exports){ // The `kern` table contains kerning pairs. // Note that some fonts use the GPOS OpenType layout table to specify kerning. // https://www.microsoft.com/typography/OTSPEC/kern.htm

'use strict';

var check = _dereq_('../check'); var parse = _dereq_('../parse');

// Parse the `kern` table which contains kerning pairs. function parseKernTable(data, start) {

   var pairs = {};
   var p = new parse.Parser(data, start);
   var tableVersion = p.parseUShort();
   check.argument(tableVersion === 0, 'Unsupported kern table version.');
   // Skip nTables.
   p.skip('uShort', 1);
   var subTableVersion = p.parseUShort();
   check.argument(subTableVersion === 0, 'Unsupported kern sub-table version.');
   // Skip subTableLength, subTableCoverage
   p.skip('uShort', 2);
   var nPairs = p.parseUShort();
   // Skip searchRange, entrySelector, rangeShift.
   p.skip('uShort', 3);
   for (var i = 0; i < nPairs; i += 1) {
       var leftIndex = p.parseUShort();
       var rightIndex = p.parseUShort();
       var value = p.parseShort();
       pairs[leftIndex + ',' + rightIndex] = value;
   }
   return pairs;

}

exports.parse = parseKernTable;

},{"../check":2,"../parse":9}],20:[function(_dereq_,module,exports){ // The `loca` table stores the offsets to the locations of the glyphs in the font. // https://www.microsoft.com/typography/OTSPEC/loca.htm

'use strict';

var parse = _dereq_('../parse');

// Parse the `loca` table. This table stores the offsets to the locations of the glyphs in the font, // relative to the beginning of the glyphData table. // The number of glyphs stored in the `loca` table is specified in the `maxp` table (under numGlyphs) // The loca table has two versions: a short version where offsets are stored as uShorts, and a long // version where offsets are stored as uLongs. The `head` table specifies which version to use // (under indexToLocFormat). function parseLocaTable(data, start, numGlyphs, shortVersion) {

   var p = new parse.Parser(data, start);
   var parseFn = shortVersion ? p.parseUShort : p.parseULong;
   // There is an extra entry after the last index element to compute the length of the last glyph.
   // That's why we use numGlyphs + 1.
   var glyphOffsets = [];
   for (var i = 0; i < numGlyphs + 1; i += 1) {
       var glyphOffset = parseFn.call(p);
       if (shortVersion) {
           // The short table version stores the actual offset divided by 2.
           glyphOffset *= 2;
       }
       glyphOffsets.push(glyphOffset);
   }
   return glyphOffsets;

}

exports.parse = parseLocaTable;

},{"../parse":9}],21:[function(_dereq_,module,exports){ // The `maxp` table establishes the memory requirements for the font. // We need it just to get the number of glyphs in the font. // https://www.microsoft.com/typography/OTSPEC/maxp.htm

'use strict';

var parse = _dereq_('../parse'); var table = _dereq_('../table');

// Parse the maximum profile `maxp` table. function parseMaxpTable(data, start) {

   var maxp = {};
   var p = new parse.Parser(data, start);
   maxp.version = p.parseVersion();
   maxp.numGlyphs = p.parseUShort();
   if (maxp.version === 1.0) {
       maxp.maxPoints = p.parseUShort();
       maxp.maxContours = p.parseUShort();
       maxp.maxCompositePoints = p.parseUShort();
       maxp.maxCompositeContours = p.parseUShort();
       maxp.maxZones = p.parseUShort();
       maxp.maxTwilightPoints = p.parseUShort();
       maxp.maxStorage = p.parseUShort();
       maxp.maxFunctionDefs = p.parseUShort();
       maxp.maxInstructionDefs = p.parseUShort();
       maxp.maxStackElements = p.parseUShort();
       maxp.maxSizeOfInstructions = p.parseUShort();
       maxp.maxComponentElements = p.parseUShort();
       maxp.maxComponentDepth = p.parseUShort();
   }
   return maxp;

}

function makeMaxpTable(numGlyphs) {

   return new table.Table('maxp', [
       {name: 'version', type: 'FIXED', value: 0x00005000},
       {name: 'numGlyphs', type: 'USHORT', value: numGlyphs}
   ]);

}

exports.parse = parseMaxpTable; exports.make = makeMaxpTable;

},{"../parse":9,"../table":11}],22:[function(_dereq_,module,exports){ // The `name` naming table. // https://www.microsoft.com/typography/OTSPEC/name.htm

'use strict';

var encode = _dereq_('../types').encode; var parse = _dereq_('../parse'); var table = _dereq_('../table');

// NameIDs for the name table. var nameTableNames = [

   'copyright',              // 0
   'fontFamily',             // 1
   'fontSubfamily',          // 2
   'uniqueID',               // 3
   'fullName',               // 4
   'version',                // 5
   'postScriptName',         // 6
   'trademark',              // 7
   'manufacturer',           // 8
   'designer',               // 9
   'description',            // 10
   'manufacturerURL',        // 11
   'designerURL',            // 12
   'licence',                // 13
   'licenceURL',             // 14
   'reserved',               // 15
   'preferredFamily',        // 16
   'preferredSubfamily',     // 17
   'compatibleFullName',     // 18
   'sampleText',             // 19
   'postScriptFindFontName', // 20
   'wwsFamily',              // 21
   'wwsSubfamily'            // 22

];

// Parse the naming `name` table // Only Windows Unicode English names are supported. // Format 1 additional fields are not supported function parseNameTable(data, start) {

   var name = {};
   var p = new parse.Parser(data, start);
   name.format = p.parseUShort();
   var count = p.parseUShort();
   var stringOffset = p.offset + p.parseUShort();
   var unknownCount = 0;
   for (var i = 0; i < count; i++) {
       var platformID = p.parseUShort();
       var encodingID = p.parseUShort();
       var languageID = p.parseUShort();
       var nameID = p.parseUShort();
       var property = nameTableNames[nameID];
       var byteLength = p.parseUShort();
       var offset = p.parseUShort();
       // platformID - encodingID - languageID standard combinations :
       // 1 - 0 - 0 : Macintosh, Roman, English
       // 3 - 1 - 0x409 : Windows, Unicode BMP (UCS-2), en-US
       if (platformID === 3 && encodingID === 1 && languageID === 0x409) {
           var codePoints = [];
           var length = byteLength / 2;
           for (var j = 0; j < length; j++, offset += 2) {
               codePoints[j] = parse.getShort(data, stringOffset + offset);
           }
           var str = String.fromCharCode.apply(null, codePoints);
           if (property) {
               name[property] = str;
           }
           else {
               unknownCount++;
               name['unknown' + unknownCount] = str;
           }
       }
   }
   if (name.format === 1) {
       name.langTagCount = p.parseUShort();
   }
   return name;

}

function makeNameRecord(platformID, encodingID, languageID, nameID, length, offset) {

   return new table.Table('NameRecord', [
       {name: 'platformID', type: 'USHORT', value: platformID},
       {name: 'encodingID', type: 'USHORT', value: encodingID},
       {name: 'languageID', type: 'USHORT', value: languageID},
       {name: 'nameID', type: 'USHORT', value: nameID},
       {name: 'length', type: 'USHORT', value: length},
       {name: 'offset', type: 'USHORT', value: offset}
   ]);

}

function addMacintoshNameRecord(t, recordID, s, offset) {

   // Macintosh, Roman, English
   var stringBytes = encode.STRING(s);
   t.records.push(makeNameRecord(1, 0, 0, recordID, stringBytes.length, offset));
   t.strings.push(stringBytes);
   offset += stringBytes.length;
   return offset;

}

function addWindowsNameRecord(t, recordID, s, offset) {

   // Windows, Unicode BMP (UCS-2), US English
   var utf16Bytes = encode.UTF16(s);
   t.records.push(makeNameRecord(3, 1, 0x0409, recordID, utf16Bytes.length, offset));
   t.strings.push(utf16Bytes);
   offset += utf16Bytes.length;
   return offset;

}

function makeNameTable(options) {

   var t = new table.Table('name', [
       {name: 'format', type: 'USHORT', value: 0},
       {name: 'count', type: 'USHORT', value: 0},
       {name: 'stringOffset', type: 'USHORT', value: 0}
   ]);
   t.records = [];
   t.strings = [];
   var offset = 0;
   var i;
   var s;
   // Add Macintosh records first
   for (i = 0; i < nameTableNames.length; i += 1) {
       if (options[nameTableNames[i]] !== undefined) {
           s = options[nameTableNames[i]];
           offset = addMacintoshNameRecord(t, i, s, offset);
       }
   }
   // Then add Windows records
   for (i = 0; i < nameTableNames.length; i += 1) {
       if (options[nameTableNames[i]] !== undefined) {
           s = options[nameTableNames[i]];
           offset = addWindowsNameRecord(t, i, s, offset);
       }
   }
   t.count = t.records.length;
   t.stringOffset = 6 + t.count * 12;
   for (i = 0; i < t.records.length; i += 1) {
       t.fields.push({name: 'record_' + i, type: 'TABLE', value: t.records[i]});
   }
   for (i = 0; i < t.strings.length; i += 1) {
       t.fields.push({name: 'string_' + i, type: 'LITERAL', value: t.strings[i]});
   }
   return t;

}

exports.parse = parseNameTable; exports.make = makeNameTable;

},{"../parse":9,"../table":11,"../types":26}],23:[function(_dereq_,module,exports){ // The `OS/2` table contains metrics required in OpenType fonts. // https://www.microsoft.com/typography/OTSPEC/os2.htm

'use strict';

var parse = _dereq_('../parse'); var table = _dereq_('../table');

var unicodeRanges = [

   {begin: 0x0000, end: 0x007F}, // Basic Latin
   {begin: 0x0080, end: 0x00FF}, // Latin-1 Supplement
   {begin: 0x0100, end: 0x017F}, // Latin Extended-A
   {begin: 0x0180, end: 0x024F}, // Latin Extended-B
   {begin: 0x0250, end: 0x02AF}, // IPA Extensions
   {begin: 0x02B0, end: 0x02FF}, // Spacing Modifier Letters
   {begin: 0x0300, end: 0x036F}, // Combining Diacritical Marks
   {begin: 0x0370, end: 0x03FF}, // Greek and Coptic
   {begin: 0x2C80, end: 0x2CFF}, // Coptic
   {begin: 0x0400, end: 0x04FF}, // Cyrillic
   {begin: 0x0530, end: 0x058F}, // Armenian
   {begin: 0x0590, end: 0x05FF}, // Hebrew
   {begin: 0xA500, end: 0xA63F}, // Vai
   {begin: 0x0600, end: 0x06FF}, // Arabic
   {begin: 0x07C0, end: 0x07FF}, // NKo
   {begin: 0x0900, end: 0x097F}, // Devanagari
   {begin: 0x0980, end: 0x09FF}, // Bengali
   {begin: 0x0A00, end: 0x0A7F}, // Gurmukhi
   {begin: 0x0A80, end: 0x0AFF}, // Gujarati
   {begin: 0x0B00, end: 0x0B7F}, // Oriya
   {begin: 0x0B80, end: 0x0BFF}, // Tamil
   {begin: 0x0C00, end: 0x0C7F}, // Telugu
   {begin: 0x0C80, end: 0x0CFF}, // Kannada
   {begin: 0x0D00, end: 0x0D7F}, // Malayalam
   {begin: 0x0E00, end: 0x0E7F}, // Thai
   {begin: 0x0E80, end: 0x0EFF}, // Lao
   {begin: 0x10A0, end: 0x10FF}, // Georgian
   {begin: 0x1B00, end: 0x1B7F}, // Balinese
   {begin: 0x1100, end: 0x11FF}, // Hangul Jamo
   {begin: 0x1E00, end: 0x1EFF}, // Latin Extended Additional
   {begin: 0x1F00, end: 0x1FFF}, // Greek Extended
   {begin: 0x2000, end: 0x206F}, // General Punctuation
   {begin: 0x2070, end: 0x209F}, // Superscripts And Subscripts
   {begin: 0x20A0, end: 0x20CF}, // Currency Symbol
   {begin: 0x20D0, end: 0x20FF}, // Combining Diacritical Marks For Symbols
   {begin: 0x2100, end: 0x214F}, // Letterlike Symbols
   {begin: 0x2150, end: 0x218F}, // Number Forms
   {begin: 0x2190, end: 0x21FF}, // Arrows
   {begin: 0x2200, end: 0x22FF}, // Mathematical Operators
   {begin: 0x2300, end: 0x23FF}, // Miscellaneous Technical
   {begin: 0x2400, end: 0x243F}, // Control Pictures
   {begin: 0x2440, end: 0x245F}, // Optical Character Recognition
   {begin: 0x2460, end: 0x24FF}, // Enclosed Alphanumerics
   {begin: 0x2500, end: 0x257F}, // Box Drawing
   {begin: 0x2580, end: 0x259F}, // Block Elements
   {begin: 0x25A0, end: 0x25FF}, // Geometric Shapes
   {begin: 0x2600, end: 0x26FF}, // Miscellaneous Symbols
   {begin: 0x2700, end: 0x27BF}, // Dingbats
   {begin: 0x3000, end: 0x303F}, // CJK Symbols And Punctuation
   {begin: 0x3040, end: 0x309F}, // Hiragana
   {begin: 0x30A0, end: 0x30FF}, // Katakana
   {begin: 0x3100, end: 0x312F}, // Bopomofo
   {begin: 0x3130, end: 0x318F}, // Hangul Compatibility Jamo
   {begin: 0xA840, end: 0xA87F}, // Phags-pa
   {begin: 0x3200, end: 0x32FF}, // Enclosed CJK Letters And Months
   {begin: 0x3300, end: 0x33FF}, // CJK Compatibility
   {begin: 0xAC00, end: 0xD7AF}, // Hangul Syllables
   {begin: 0xD800, end: 0xDFFF}, // Non-Plane 0 *
   {begin: 0x10900, end: 0x1091F}, // Phoenicia
   {begin: 0x4E00, end: 0x9FFF}, // CJK Unified Ideographs
   {begin: 0xE000, end: 0xF8FF}, // Private Use Area (plane 0)
   {begin: 0x31C0, end: 0x31EF}, // CJK Strokes
   {begin: 0xFB00, end: 0xFB4F}, // Alphabetic Presentation Forms
   {begin: 0xFB50, end: 0xFDFF}, // Arabic Presentation Forms-A
   {begin: 0xFE20, end: 0xFE2F}, // Combining Half Marks
   {begin: 0xFE10, end: 0xFE1F}, // Vertical Forms
   {begin: 0xFE50, end: 0xFE6F}, // Small Form Variants
   {begin: 0xFE70, end: 0xFEFF}, // Arabic Presentation Forms-B
   {begin: 0xFF00, end: 0xFFEF}, // Halfwidth And Fullwidth Forms
   {begin: 0xFFF0, end: 0xFFFF}, // Specials
   {begin: 0x0F00, end: 0x0FFF}, // Tibetan
   {begin: 0x0700, end: 0x074F}, // Syriac
   {begin: 0x0780, end: 0x07BF}, // Thaana
   {begin: 0x0D80, end: 0x0DFF}, // Sinhala
   {begin: 0x1000, end: 0x109F}, // Myanmar
   {begin: 0x1200, end: 0x137F}, // Ethiopic
   {begin: 0x13A0, end: 0x13FF}, // Cherokee
   {begin: 0x1400, end: 0x167F}, // Unified Canadian Aboriginal Syllabics
   {begin: 0x1680, end: 0x169F}, // Ogham
   {begin: 0x16A0, end: 0x16FF}, // Runic
   {begin: 0x1780, end: 0x17FF}, // Khmer
   {begin: 0x1800, end: 0x18AF}, // Mongolian
   {begin: 0x2800, end: 0x28FF}, // Braille Patterns
   {begin: 0xA000, end: 0xA48F}, // Yi Syllables
   {begin: 0x1700, end: 0x171F}, // Tagalog
   {begin: 0x10300, end: 0x1032F}, // Old Italic
   {begin: 0x10330, end: 0x1034F}, // Gothic
   {begin: 0x10400, end: 0x1044F}, // Deseret
   {begin: 0x1D000, end: 0x1D0FF}, // Byzantine Musical Symbols
   {begin: 0x1D400, end: 0x1D7FF}, // Mathematical Alphanumeric Symbols
   {begin: 0xFF000, end: 0xFFFFD}, // Private Use (plane 15)
   {begin: 0xFE00, end: 0xFE0F}, // Variation Selectors
   {begin: 0xE0000, end: 0xE007F}, // Tags
   {begin: 0x1900, end: 0x194F}, // Limbu
   {begin: 0x1950, end: 0x197F}, // Tai Le
   {begin: 0x1980, end: 0x19DF}, // New Tai Lue
   {begin: 0x1A00, end: 0x1A1F}, // Buginese
   {begin: 0x2C00, end: 0x2C5F}, // Glagolitic
   {begin: 0x2D30, end: 0x2D7F}, // Tifinagh
   {begin: 0x4DC0, end: 0x4DFF}, // Yijing Hexagram Symbols
   {begin: 0xA800, end: 0xA82F}, // Syloti Nagri
   {begin: 0x10000, end: 0x1007F}, // Linear B Syllabary
   {begin: 0x10140, end: 0x1018F}, // Ancient Greek Numbers
   {begin: 0x10380, end: 0x1039F}, // Ugaritic
   {begin: 0x103A0, end: 0x103DF}, // Old Persian
   {begin: 0x10450, end: 0x1047F}, // Shavian
   {begin: 0x10480, end: 0x104AF}, // Osmanya
   {begin: 0x10800, end: 0x1083F}, // Cypriot Syllabary
   {begin: 0x10A00, end: 0x10A5F}, // Kharoshthi
   {begin: 0x1D300, end: 0x1D35F}, // Tai Xuan Jing Symbols
   {begin: 0x12000, end: 0x123FF}, // Cuneiform
   {begin: 0x1D360, end: 0x1D37F}, // Counting Rod Numerals
   {begin: 0x1B80, end: 0x1BBF}, // Sundanese
   {begin: 0x1C00, end: 0x1C4F}, // Lepcha
   {begin: 0x1C50, end: 0x1C7F}, // Ol Chiki
   {begin: 0xA880, end: 0xA8DF}, // Saurashtra
   {begin: 0xA900, end: 0xA92F}, // Kayah Li
   {begin: 0xA930, end: 0xA95F}, // Rejang
   {begin: 0xAA00, end: 0xAA5F}, // Cham
   {begin: 0x10190, end: 0x101CF}, // Ancient Symbols
   {begin: 0x101D0, end: 0x101FF}, // Phaistos Disc
   {begin: 0x102A0, end: 0x102DF}, // Carian
   {begin: 0x1F030, end: 0x1F09F}  // Domino Tiles

];

function getUnicodeRange(unicode) {

   for (var i = 0; i < unicodeRanges.length; i += 1) {
       var range = unicodeRanges[i];
       if (unicode >= range.begin && unicode < range.end) {
           return i;
       }
   }
   return -1;

}

// Parse the OS/2 and Windows metrics `OS/2` table function parseOS2Table(data, start) {

   var os2 = {};
   var p = new parse.Parser(data, start);
   os2.version = p.parseUShort();
   os2.xAvgCharWidth = p.parseShort();
   os2.usWeightClass = p.parseUShort();
   os2.usWidthClass = p.parseUShort();
   os2.fsType = p.parseUShort();
   os2.ySubscriptXSize = p.parseShort();
   os2.ySubscriptYSize = p.parseShort();
   os2.ySubscriptXOffset = p.parseShort();
   os2.ySubscriptYOffset = p.parseShort();
   os2.ySuperscriptXSize = p.parseShort();
   os2.ySuperscriptYSize = p.parseShort();
   os2.ySuperscriptXOffset = p.parseShort();
   os2.ySuperscriptYOffset = p.parseShort();
   os2.yStrikeoutSize = p.parseShort();
   os2.yStrikeoutPosition = p.parseShort();
   os2.sFamilyClass = p.parseShort();
   os2.panose = [];
   for (var i = 0; i < 10; i++) {
       os2.panose[i] = p.parseByte();
   }
   os2.ulUnicodeRange1 = p.parseULong();
   os2.ulUnicodeRange2 = p.parseULong();
   os2.ulUnicodeRange3 = p.parseULong();
   os2.ulUnicodeRange4 = p.parseULong();
   os2.achVendID = String.fromCharCode(p.parseByte(), p.parseByte(), p.parseByte(), p.parseByte());
   os2.fsSelection = p.parseUShort();
   os2.usFirstCharIndex = p.parseUShort();
   os2.usLastCharIndex = p.parseUShort();
   os2.sTypoAscender = p.parseShort();
   os2.sTypoDescender = p.parseShort();
   os2.sTypoLineGap = p.parseShort();
   os2.usWinAscent = p.parseUShort();
   os2.usWinDescent = p.parseUShort();
   if (os2.version >= 1) {
       os2.ulCodePageRange1 = p.parseULong();
       os2.ulCodePageRange2 = p.parseULong();
   }
   if (os2.version >= 2) {
       os2.sxHeight = p.parseShort();
       os2.sCapHeight = p.parseShort();
       os2.usDefaultChar = p.parseUShort();
       os2.usBreakChar = p.parseUShort();
       os2.usMaxContent = p.parseUShort();
   }
   return os2;

}

function makeOS2Table(options) {

   return new table.Table('OS/2', [
       {name: 'version', type: 'USHORT', value: 0x0003},
       {name: 'xAvgCharWidth', type: 'SHORT', value: 0},
       {name: 'usWeightClass', type: 'USHORT', value: 0},
       {name: 'usWidthClass', type: 'USHORT', value: 0},
       {name: 'fsType', type: 'USHORT', value: 0},
       {name: 'ySubscriptXSize', type: 'SHORT', value: 650},
       {name: 'ySubscriptYSize', type: 'SHORT', value: 699},
       {name: 'ySubscriptXOffset', type: 'SHORT', value: 0},
       {name: 'ySubscriptYOffset', type: 'SHORT', value: 140},
       {name: 'ySuperscriptXSize', type: 'SHORT', value: 650},
       {name: 'ySuperscriptYSize', type: 'SHORT', value: 699},
       {name: 'ySuperscriptXOffset', type: 'SHORT', value: 0},
       {name: 'ySuperscriptYOffset', type: 'SHORT', value: 479},
       {name: 'yStrikeoutSize', type: 'SHORT', value: 49},
       {name: 'yStrikeoutPosition', type: 'SHORT', value: 258},
       {name: 'sFamilyClass', type: 'SHORT', value: 0},
       {name: 'bFamilyType', type: 'BYTE', value: 0},
       {name: 'bSerifStyle', type: 'BYTE', value: 0},
       {name: 'bWeight', type: 'BYTE', value: 0},
       {name: 'bProportion', type: 'BYTE', value: 0},
       {name: 'bContrast', type: 'BYTE', value: 0},
       {name: 'bStrokeVariation', type: 'BYTE', value: 0},
       {name: 'bArmStyle', type: 'BYTE', value: 0},
       {name: 'bLetterform', type: 'BYTE', value: 0},
       {name: 'bMidline', type: 'BYTE', value: 0},
       {name: 'bXHeight', type: 'BYTE', value: 0},
       {name: 'ulUnicodeRange1', type: 'ULONG', value: 0},
       {name: 'ulUnicodeRange2', type: 'ULONG', value: 0},
       {name: 'ulUnicodeRange3', type: 'ULONG', value: 0},
       {name: 'ulUnicodeRange4', type: 'ULONG', value: 0},
       {name: 'achVendID', type: 'CHARARRAY', value: 'XXXX'},
       {name: 'fsSelection', type: 'USHORT', value: 0},
       {name: 'usFirstCharIndex', type: 'USHORT', value: 0},
       {name: 'usLastCharIndex', type: 'USHORT', value: 0},
       {name: 'sTypoAscender', type: 'SHORT', value: 0},
       {name: 'sTypoDescender', type: 'SHORT', value: 0},
       {name: 'sTypoLineGap', type: 'SHORT', value: 0},
       {name: 'usWinAscent', type: 'USHORT', value: 0},
       {name: 'usWinDescent', type: 'USHORT', value: 0},
       {name: 'ulCodePageRange1', type: 'ULONG', value: 0},
       {name: 'ulCodePageRange2', type: 'ULONG', value: 0},
       {name: 'sxHeight', type: 'SHORT', value: 0},
       {name: 'sCapHeight', type: 'SHORT', value: 0},
       {name: 'usDefaultChar', type: 'USHORT', value: 0},
       {name: 'usBreakChar', type: 'USHORT', value: 0},
       {name: 'usMaxContext', type: 'USHORT', value: 0}
   ], options);

}

exports.unicodeRanges = unicodeRanges; exports.getUnicodeRange = getUnicodeRange; exports.parse = parseOS2Table; exports.make = makeOS2Table;

},{"../parse":9,"../table":11}],24:[function(_dereq_,module,exports){ // The `post` table stores additional PostScript information, such as glyph names. // https://www.microsoft.com/typography/OTSPEC/post.htm

'use strict';

var encoding = _dereq_('../encoding'); var parse = _dereq_('../parse'); var table = _dereq_('../table');

// Parse the PostScript `post` table function parsePostTable(data, start) {

   var post = {};
   var p = new parse.Parser(data, start);
   var i;
   post.version = p.parseVersion();
   post.italicAngle = p.parseFixed();
   post.underlinePosition = p.parseShort();
   post.underlineThickness = p.parseShort();
   post.isFixedPitch = p.parseULong();
   post.minMemType42 = p.parseULong();
   post.maxMemType42 = p.parseULong();
   post.minMemType1 = p.parseULong();
   post.maxMemType1 = p.parseULong();
   switch (post.version) {
   case 1:
       post.names = encoding.standardNames.slice();
       break;
   case 2:
       post.numberOfGlyphs = p.parseUShort();
       post.glyphNameIndex = new Array(post.numberOfGlyphs);
       for (i = 0; i < post.numberOfGlyphs; i++) {
           post.glyphNameIndex[i] = p.parseUShort();
       }
       post.names = [];
       for (i = 0; i < post.numberOfGlyphs; i++) {
           if (post.glyphNameIndex[i] >= encoding.standardNames.length) {
               var nameLength = p.parseChar();
               post.names.push(p.parseString(nameLength));
           }
       }
       break;
   case 2.5:
       post.numberOfGlyphs = p.parseUShort();
       post.offset = new Array(post.numberOfGlyphs);
       for (i = 0; i < post.numberOfGlyphs; i++) {
           post.offset[i] = p.parseChar();
       }
       break;
   }
   return post;

}

function makePostTable() {

   return new table.Table('post', [
       {name: 'version', type: 'FIXED', value: 0x00030000},
       {name: 'italicAngle', type: 'FIXED', value: 0},
       {name: 'underlinePosition', type: 'FWORD', value: 0},
       {name: 'underlineThickness', type: 'FWORD', value: 0},
       {name: 'isFixedPitch', type: 'ULONG', value: 0},
       {name: 'minMemType42', type: 'ULONG', value: 0},
       {name: 'maxMemType42', type: 'ULONG', value: 0},
       {name: 'minMemType1', type: 'ULONG', value: 0},
       {name: 'maxMemType1', type: 'ULONG', value: 0}
   ]);

}

exports.parse = parsePostTable; exports.make = makePostTable;

},{"../encoding":4,"../parse":9,"../table":11}],25:[function(_dereq_,module,exports){ // The `sfnt` wrapper provides organization for the tables in the font. // It is the top-level data structure in a font. // https://www.microsoft.com/typography/OTSPEC/otff.htm // Recommendations for creating OpenType Fonts: // http://www.microsoft.com/typography/otspec140/recom.htm

'use strict';

var check = _dereq_('../check'); var table = _dereq_('../table');

var cmap = _dereq_('./cmap'); var cff = _dereq_('./cff'); var head = _dereq_('./head'); var hhea = _dereq_('./hhea'); var hmtx = _dereq_('./hmtx'); var maxp = _dereq_('./maxp'); var _name = _dereq_('./name'); var os2 = _dereq_('./os2'); var post = _dereq_('./post');

function log2(v) {

   return Math.log(v) / Math.log(2) | 0;

}

function computeCheckSum(bytes) {

   while (bytes.length % 4 !== 0) {
       bytes.push(0);
   }
   var sum = 0;
   for (var i = 0; i < bytes.length; i += 4) {
       sum += (bytes[i] << 24) +
           (bytes[i + 1] << 16) +
           (bytes[i + 2] << 8) +
           (bytes[i + 3]);
   }
   sum %= Math.pow(2, 32);
   return sum;

}

function makeTableRecord(tag, checkSum, offset, length) {

   return new table.Table('Table Record', [
       {name: 'tag', type: 'TAG', value: tag !== undefined ? tag : },
       {name: 'checkSum', type: 'ULONG', value: checkSum !== undefined ? checkSum : 0},
       {name: 'offset', type: 'ULONG', value: offset !== undefined ? offset : 0},
       {name: 'length', type: 'ULONG', value: length !== undefined ? length : 0}
   ]);

}

function makeSfntTable(tables) {

   var sfnt = new table.Table('sfnt', [
       {name: 'version', type: 'TAG', value: 'OTTO'},
       {name: 'numTables', type: 'USHORT', value: 0},
       {name: 'searchRange', type: 'USHORT', value: 0},
       {name: 'entrySelector', type: 'USHORT', value: 0},
       {name: 'rangeShift', type: 'USHORT', value: 0}
   ]);
   sfnt.tables = tables;
   sfnt.numTables = tables.length;
   var highestPowerOf2 = Math.pow(2, log2(sfnt.numTables));
   sfnt.searchRange = 16 * highestPowerOf2;
   sfnt.entrySelector = log2(highestPowerOf2);
   sfnt.rangeShift = sfnt.numTables * 16 - sfnt.searchRange;
   var recordFields = [];
   var tableFields = [];
   var offset = sfnt.sizeOf() + (makeTableRecord().sizeOf() * sfnt.numTables);
   while (offset % 4 !== 0) {
       offset += 1;
       tableFields.push({name: 'padding', type: 'BYTE', value: 0});
   }
   for (var i = 0; i < tables.length; i += 1) {
       var t = tables[i];
       check.argument(t.tableName.length === 4, 'Table name' + t.tableName + ' is invalid.');
       var tableLength = t.sizeOf();
       var tableRecord = makeTableRecord(t.tableName, computeCheckSum(t.encode()), offset, tableLength);
       recordFields.push({name: tableRecord.tag + ' Table Record', type: 'TABLE', value: tableRecord});
       tableFields.push({name: t.tableName + ' table', type: 'TABLE', value: t});
       offset += tableLength;
       check.argument(!isNaN(offset), 'Something went wrong calculating the offset.');
       while (offset % 4 !== 0) {
           offset += 1;
           tableFields.push({name: 'padding', type: 'BYTE', value: 0});
       }
   }
   // Table records need to be sorted alphabetically.
   recordFields.sort(function(r1, r2) {
       if (r1.value.tag > r2.value.tag) {
           return 1;
       } else {
           return -1;
       }
   });
   sfnt.fields = sfnt.fields.concat(recordFields);
   sfnt.fields = sfnt.fields.concat(tableFields);
   return sfnt;

}

// Get the metrics for a character. If the string has more than one character // this function returns metrics for the first available character. // You can provide optional fallback metrics if no characters are available. function metricsForChar(font, chars, notFoundMetrics) {

   for (var i = 0; i < chars.length; i += 1) {
       var glyphIndex = font.charToGlyphIndex(chars[i]);
       if (glyphIndex > 0) {
           var glyph = font.glyphs.get(glyphIndex);
           return glyph.getMetrics();
       }
   }
   return notFoundMetrics;

}

function average(vs) {

   var sum = 0;
   for (var i = 0; i < vs.length; i += 1) {
       sum += vs[i];
   }
   return sum / vs.length;

}

// Convert the font object to a SFNT data structure. // This structure contains all the necessary tables and metadata to create a binary OTF file. function fontToSfntTable(font) {

   var xMins = [];
   var yMins = [];
   var xMaxs = [];
   var yMaxs = [];
   var advanceWidths = [];
   var leftSideBearings = [];
   var rightSideBearings = [];
   var firstCharIndex;
   var lastCharIndex = 0;
   var ulUnicodeRange1 = 0;
   var ulUnicodeRange2 = 0;
   var ulUnicodeRange3 = 0;
   var ulUnicodeRange4 = 0;
   for (var i = 0; i < font.glyphs.length; i += 1) {
       var glyph = font.glyphs.get(i);
       var unicode = glyph.unicode | 0;
       if (firstCharIndex > unicode || firstCharIndex === null) {
           firstCharIndex = unicode;
       }
       if (lastCharIndex < unicode) {
           lastCharIndex = unicode;
       }
       var position = os2.getUnicodeRange(unicode);
       if (position < 32) {
           ulUnicodeRange1 |= 1 << position;
       } else if (position < 64) {
           ulUnicodeRange2 |= 1 << position - 32;
       } else if (position < 96) {
           ulUnicodeRange3 |= 1 << position - 64;
       } else if (position < 123) {
           ulUnicodeRange4 |= 1 << position - 96;
       } else {
           throw new Error('Unicode ranges bits > 123 are reserved for internal usage');
       }
       // Skip non-important characters.
       if (glyph.name === '.notdef') continue;
       var metrics = glyph.getMetrics();
       xMins.push(metrics.xMin);
       yMins.push(metrics.yMin);
       xMaxs.push(metrics.xMax);
       yMaxs.push(metrics.yMax);
       leftSideBearings.push(metrics.leftSideBearing);
       rightSideBearings.push(metrics.rightSideBearing);
       advanceWidths.push(glyph.advanceWidth);
   }
   var globals = {
       xMin: Math.min.apply(null, xMins),
       yMin: Math.min.apply(null, yMins),
       xMax: Math.max.apply(null, xMaxs),
       yMax: Math.max.apply(null, yMaxs),
       advanceWidthMax: Math.max.apply(null, advanceWidths),
       advanceWidthAvg: average(advanceWidths),
       minLeftSideBearing: Math.min.apply(null, leftSideBearings),
       maxLeftSideBearing: Math.max.apply(null, leftSideBearings),
       minRightSideBearing: Math.min.apply(null, rightSideBearings)
   };
   globals.ascender = font.ascender !== undefined ? font.ascender : globals.yMax;
   globals.descender = font.descender !== undefined ? font.descender : globals.yMin;
   var headTable = head.make({
       unitsPerEm: font.unitsPerEm,
       xMin: globals.xMin,
       yMin: globals.yMin,
       xMax: globals.xMax,
       yMax: globals.yMax
   });
   var hheaTable = hhea.make({
       ascender: globals.ascender,
       descender: globals.descender,
       advanceWidthMax: globals.advanceWidthMax,
       minLeftSideBearing: globals.minLeftSideBearing,
       minRightSideBearing: globals.minRightSideBearing,
       xMaxExtent: globals.maxLeftSideBearing + (globals.xMax - globals.xMin),
       numberOfHMetrics: font.glyphs.length
   });
   var maxpTable = maxp.make(font.glyphs.length);
   var os2Table = os2.make({
       xAvgCharWidth: Math.round(globals.advanceWidthAvg),
       usWeightClass: 500, // Medium FIXME Make this configurable
       usWidthClass: 5, // Medium (normal) FIXME Make this configurable
       usFirstCharIndex: firstCharIndex,
       usLastCharIndex: lastCharIndex,
       ulUnicodeRange1: ulUnicodeRange1,
       ulUnicodeRange2: ulUnicodeRange2,
       ulUnicodeRange3: ulUnicodeRange3,
       ulUnicodeRange4: ulUnicodeRange4,
       // See http://typophile.com/node/13081 for more info on vertical metrics.
       // We get metrics for typical characters (such as "x" for xHeight).
       // We provide some fallback characters if characters are unavailable: their
       // ordering was chosen experimentally.
       sTypoAscender: globals.ascender,
       sTypoDescender: globals.descender,
       sTypoLineGap: 0,
       usWinAscent: globals.ascender,
       usWinDescent: -globals.descender,
       sxHeight: metricsForChar(font, 'xyvw', {yMax: 0}).yMax,
       sCapHeight: metricsForChar(font, 'HIKLEFJMNTZBDPRAGOQSUVWXY', globals).yMax,
       usBreakChar: font.hasChar(' ') ? 32 : 0 // Use space as the break character, if available.
   });
   var hmtxTable = hmtx.make(font.glyphs);
   var cmapTable = cmap.make(font.glyphs);
   var fullName = font.familyName + ' ' + font.styleName;
   var postScriptName = font.familyName.replace(/\s/g, ) + '-' + font.styleName;
   var nameTable = _name.make({
       copyright: font.copyright,
       fontFamily: font.familyName,
       fontSubfamily: font.styleName,
       uniqueID: font.manufacturer + ':' + fullName,
       fullName: fullName,
       version: font.version,
       postScriptName: postScriptName,
       trademark: font.trademark,
       manufacturer: font.manufacturer,
       designer: font.designer,
       description: font.description,
       manufacturerURL: font.manufacturerURL,
       designerURL: font.designerURL,
       license: font.license,
       licenseURL: font.licenseURL,
       preferredFamily: font.familyName,
       preferredSubfamily: font.styleName
   });
   var postTable = post.make();
   var cffTable = cff.make(font.glyphs, {
       version: font.version,
       fullName: fullName,
       familyName: font.familyName,
       weightName: font.styleName,
       postScriptName: postScriptName,
       unitsPerEm: font.unitsPerEm
   });
   // Order the tables according to the the OpenType specification 1.4.
   var tables = [headTable, hheaTable, maxpTable, os2Table, nameTable, cmapTable, postTable, cffTable, hmtxTable];
   var sfntTable = makeSfntTable(tables);
   // Compute the font's checkSum and store it in head.checkSumAdjustment.
   var bytes = sfntTable.encode();
   var checkSum = computeCheckSum(bytes);
   var tableFields = sfntTable.fields;
   var checkSumAdjusted = false;
   for (i = 0; i < tableFields.length; i += 1) {
       if (tableFields[i].name === 'head table') {
           tableFields[i].value.checkSumAdjustment = 0xB1B0AFBA - checkSum;
           checkSumAdjusted = true;
           break;
       }
   }
   if (!checkSumAdjusted) {
       throw new Error('Could not find head table with checkSum to adjust.');
   }
   return sfntTable;

}

exports.computeCheckSum = computeCheckSum; exports.make = makeSfntTable; exports.fontToTable = fontToSfntTable;

},{"../check":2,"../table":11,"./cff":12,"./cmap":13,"./head":16,"./hhea":17,"./hmtx":18,"./maxp":21,"./name":22,"./os2":23,"./post":24}],26:[function(_dereq_,module,exports){ // Data types used in the OpenType font file. // All OpenType fonts use Motorola-style byte ordering (Big Endian)

/* global WeakMap */

'use strict';

var check = _dereq_('./check');

var LIMIT16 = 32768; // The limit at which a 16-bit number switches signs == 2^15 var LIMIT32 = 2147483648; // The limit at which a 32-bit number switches signs == 2 ^ 31

var decode = {}; var encode = {}; var sizeOf = {};

// Return a function that always returns the same value. function constant(v) {

   return function() {
       return v;
   };

}

// OpenType data types //////////////////////////////////////////////////////

// Convert an 8-bit unsigned integer to a list of 1 byte. encode.BYTE = function(v) {

   check.argument(v >= 0 && v <= 255, 'Byte value should be between 0 and 255.');
   return [v];

};

sizeOf.BYTE = constant(1);

// Convert a 8-bit signed integer to a list of 1 byte. encode.CHAR = function(v) {

   return [v.charCodeAt(0)];

};

sizeOf.BYTE = constant(1);

// Convert an ASCII string to a list of bytes. encode.CHARARRAY = function(v) {

   var b = [];
   for (var i = 0; i < v.length; i += 1) {
       b.push(v.charCodeAt(i));
   }
   return b;

};

sizeOf.CHARARRAY = function(v) {

   return v.length;

};

// Convert a 16-bit unsigned integer to a list of 2 bytes. encode.USHORT = function(v) {

   return [(v >> 8) & 0xFF, v & 0xFF];

};

sizeOf.USHORT = constant(2);

// Convert a 16-bit signed integer to a list of 2 bytes. encode.SHORT = function(v) {

   // Two's complement
   if (v >= LIMIT16) {
       v = -(2 * LIMIT16 - v);
   }
   return [(v >> 8) & 0xFF, v & 0xFF];

};

sizeOf.SHORT = constant(2);

// Convert a 24-bit unsigned integer to a list of 3 bytes. encode.UINT24 = function(v) {

   return [(v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];

};

sizeOf.UINT24 = constant(3);

// Convert a 32-bit unsigned integer to a list of 4 bytes. encode.ULONG = function(v) {

   return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];

};

sizeOf.ULONG = constant(4);

// Convert a 32-bit unsigned integer to a list of 4 bytes. encode.LONG = function(v) {

   // Two's complement
   if (v >= LIMIT32) {
       v = -(2 * LIMIT32 - v);
   }
   return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];

};

sizeOf.LONG = constant(4);

encode.FIXED = encode.ULONG; sizeOf.FIXED = sizeOf.ULONG;

encode.FWORD = encode.SHORT; sizeOf.FWORD = sizeOf.SHORT;

encode.UFWORD = encode.USHORT; sizeOf.UFWORD = sizeOf.USHORT;

// FIXME Implement LONGDATETIME encode.LONGDATETIME = function() {

   return [0, 0, 0, 0, 0, 0, 0, 0];

};

sizeOf.LONGDATETIME = constant(8);

// Convert a 4-char tag to a list of 4 bytes. encode.TAG = function(v) {

   check.argument(v.length === 4, 'Tag should be exactly 4 ASCII characters.');
   return [v.charCodeAt(0),
           v.charCodeAt(1),
           v.charCodeAt(2),
           v.charCodeAt(3)];

};

sizeOf.TAG = constant(4);

// CFF data types ///////////////////////////////////////////////////////////

encode.Card8 = encode.BYTE; sizeOf.Card8 = sizeOf.BYTE;

encode.Card16 = encode.USHORT; sizeOf.Card16 = sizeOf.USHORT;

encode.OffSize = encode.BYTE; sizeOf.OffSize = sizeOf.BYTE;

encode.SID = encode.USHORT; sizeOf.SID = sizeOf.USHORT;

// Convert a numeric operand or charstring number to a variable-size list of bytes. encode.NUMBER = function(v) {

   if (v >= -107 && v <= 107) {
       return [v + 139];
   } else if (v >= 108 && v <= 1131) {
       v = v - 108;
       return [(v >> 8) + 247, v & 0xFF];
   } else if (v >= -1131 && v <= -108) {
       v = -v - 108;
       return [(v >> 8) + 251, v & 0xFF];
   } else if (v >= -32768 && v <= 32767) {
       return encode.NUMBER16(v);
   } else {
       return encode.NUMBER32(v);
   }

};

sizeOf.NUMBER = function(v) {

   return encode.NUMBER(v).length;

};

// Convert a signed number between -32768 and +32767 to a three-byte value. // This ensures we always use three bytes, but is not the most compact format. encode.NUMBER16 = function(v) {

   return [28, (v >> 8) & 0xFF, v & 0xFF];

};

sizeOf.NUMBER16 = constant(2);

// Convert a signed number between -(2^31) and +(2^31-1) to a four-byte value. // This is useful if you want to be sure you always use four bytes, // at the expense of wasting a few bytes for smaller numbers. encode.NUMBER32 = function(v) {

   return [29, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];

};

sizeOf.NUMBER32 = constant(4);

encode.REAL = function(v) {

   var value = v.toString();
   // Some numbers use an epsilon to encode the value. (e.g. JavaScript will store 0.0000001 as 1e-7)
   // This code converts it back to a number without the epsilon.
   var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value);
   if (m) {
       var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));
       value = (Math.round(v * epsilon) / epsilon).toString();
   }
   var nibbles = ;
   var i;
   var ii;
   for (i = 0, ii = value.length; i < ii; i += 1) {
       var c = value[i];
       if (c === 'e') {
           nibbles += value[++i] === '-' ? 'c' : 'b';
       } else if (c === '.') {
           nibbles += 'a';
       } else if (c === '-') {
           nibbles += 'e';
       } else {
           nibbles += c;
       }
   }
   nibbles += (nibbles.length & 1) ? 'f' : 'ff';
   var out = [30];
   for (i = 0, ii = nibbles.length; i < ii; i += 2) {
       out.push(parseInt(nibbles.substr(i, 2), 16));
   }
   return out;

};

sizeOf.REAL = function(v) {

   return encode.REAL(v).length;

};

encode.NAME = encode.CHARARRAY; sizeOf.NAME = sizeOf.CHARARRAY;

encode.STRING = encode.CHARARRAY; sizeOf.STRING = sizeOf.CHARARRAY;

// Convert a ASCII string to a list of UTF16 bytes. encode.UTF16 = function(v) {

   var b = [];
   for (var i = 0; i < v.length; i += 1) {
       b.push(0);
       b.push(v.charCodeAt(i));
   }
   return b;

};

sizeOf.UTF16 = function(v) {

   return v.length * 2;

};

// Convert a list of values to a CFF INDEX structure. // The values should be objects containing name / type / value. encode.INDEX = function(l) {

   var i;
   //var offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data,
   //    dataSize, i, v;
   // Because we have to know which data type to use to encode the offsets,
   // we have to go through the values twice: once to encode the data and
   // calculate the offets, then again to encode the offsets using the fitting data type.
   var offset = 1; // First offset is always 1.
   var offsets = [offset];
   var data = [];
   var dataSize = 0;
   for (i = 0; i < l.length; i += 1) {
       var v = encode.OBJECT(l[i]);
       Array.prototype.push.apply(data, v);
       dataSize += v.length;
       offset += v.length;
       offsets.push(offset);
   }
   if (data.length === 0) {
       return [0, 0];
   }
   var encodedOffsets = [];
   var offSize = (1 + Math.floor(Math.log(dataSize) / Math.log(2)) / 8) | 0;
   var offsetEncoder = [undefined, encode.BYTE, encode.USHORT, encode.UINT24, encode.ULONG][offSize];
   for (i = 0; i < offsets.length; i += 1) {
       var encodedOffset = offsetEncoder(offsets[i]);
       Array.prototype.push.apply(encodedOffsets, encodedOffset);
   }
   return Array.prototype.concat(encode.Card16(l.length),
                          encode.OffSize(offSize),
                          encodedOffsets,
                          data);

};

sizeOf.INDEX = function(v) {

   return encode.INDEX(v).length;

};

// Convert an object to a CFF DICT structure. // The keys should be numeric. // The values should be objects containing name / type / value. encode.DICT = function(m) {

   var d = [];
   var keys = Object.keys(m);
   var length = keys.length;
   for (var i = 0; i < length; i += 1) {
       // Object.keys() return string keys, but our keys are always numeric.
       var k = parseInt(keys[i], 0);
       var v = m[k];
       // Value comes before the key.
       d = d.concat(encode.OPERAND(v.value, v.type));
       d = d.concat(encode.OPERATOR(k));
   }
   return d;

};

sizeOf.DICT = function(m) {

   return encode.DICT(m).length;

};

encode.OPERATOR = function(v) {

   if (v < 1200) {
       return [v];
   } else {
       return [12, v - 1200];
   }

};

encode.OPERAND = function(v, type) {

   var d = [];
   if (Array.isArray(type)) {
       for (var i = 0; i < type.length; i += 1) {
           check.argument(v.length === type.length, 'Not enough arguments given for type' + type);
           d = d.concat(encode.OPERAND(v[i], type[i]));
       }
   } else {
       if (type === 'SID') {
           d = d.concat(encode.NUMBER(v));
       } else if (type === 'offset') {
           // We make it easy for ourselves and always encode offsets as
           // 4 bytes. This makes offset calculation for the top dict easier.
           d = d.concat(encode.NUMBER32(v));
       } else if (type === 'number') {
           d = d.concat(encode.NUMBER(v));
       } else if (type === 'real') {
           d = d.concat(encode.REAL(v));
       } else {
           throw new Error('Unknown operand type ' + type);
           // FIXME Add support for booleans
       }
   }
   return d;

};

encode.OP = encode.BYTE; sizeOf.OP = sizeOf.BYTE;

// memoize charstring encoding using WeakMap if available var wmm = typeof WeakMap === 'function' && new WeakMap(); // Convert a list of CharString operations to bytes. encode.CHARSTRING = function(ops) {

   if (wmm && wmm.has(ops)) {
       return wmm.get(ops);
   }
   var d = [];
   var length = ops.length;
   for (var i = 0; i < length; i += 1) {
       var op = ops[i];
       d = d.concat(encode[op.type](op.value));
   }
   if (wmm) {
       wmm.set(ops, d);
   }
   return d;

};

sizeOf.CHARSTRING = function(ops) {

   return encode.CHARSTRING(ops).length;

};

// Utility functions ////////////////////////////////////////////////////////

// Convert an object containing name / type / value to bytes. encode.OBJECT = function(v) {

   var encodingFunction = encode[v.type];
   check.argument(encodingFunction !== undefined, 'No encoding function for type ' + v.type);
   return encodingFunction(v.value);

};

// Convert a table object to bytes. // A table contains a list of fields containing the metadata (name, type and default value). // The table itself has the field values set as attributes. encode.TABLE = function(table) {

   var d = [];
   var length = table.fields.length;
   for (var i = 0; i < length; i += 1) {
       var field = table.fields[i];
       var encodingFunction = encode[field.type];
       check.argument(encodingFunction !== undefined, 'No encoding function for field type ' + field.type);
       var value = table[field.name];
       if (value === undefined) {
           value = field.value;
       }
       var bytes = encodingFunction(value);
       d = d.concat(bytes);
   }
   return d;

};

// Merge in a list of bytes. encode.LITERAL = function(v) {

   return v;

};

sizeOf.LITERAL = function(v) {

   return v.length;

};

exports.decode = decode; exports.encode = encode; exports.sizeOf = sizeOf;

},{"./check":2}],27:[function(_dereq_,module,exports){ /*!

 * Reqwest! A general purpose XHR connection manager
 * license MIT (c) Dustin Diaz 2014
 * https://github.com/ded/reqwest
 */

!function (name, context, definition) {

 if (typeof module != 'undefined' && module.exports) module.exports = definition()
 else if (typeof define == 'function' && define.amd) define(definition)
 else context[name] = definition()

}('reqwest', this, function () {

 var win = window
   , doc = document
   , httpsRe = /^http/
   , protocolRe = /(^\w+):\/\//
   , twoHundo = /^(20\d|1223)$/ //http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
   , byTag = 'getElementsByTagName'
   , readyState = 'readyState'
   , contentType = 'Content-Type'
   , requestedWith = 'X-Requested-With'
   , head = doc[byTag]('head')[0]
   , uniqid = 0
   , callbackPrefix = 'reqwest_' + (+new Date())
   , lastValue // data stored by the most recent JSONP callback
   , xmlHttpRequest = 'XMLHttpRequest'
   , xDomainRequest = 'XDomainRequest'
   , noop = function () {}
   , isArray = typeof Array.isArray == 'function'
       ? Array.isArray
       : function (a) {
           return a instanceof Array
         }
   , defaultHeaders = {
         'contentType': 'application/x-www-form-urlencoded'
       , 'requestedWith': xmlHttpRequest
       , 'accept': {
             '*':  'text/javascript, text/html, application/xml, text/xml, */*'
           , 'xml':  'application/xml, text/xml'
           , 'html': 'text/html'
           , 'text': 'text/plain'
           , 'json': 'application/json, text/javascript'
           , 'js':   'application/javascript, text/javascript'
         }
     }
   , xhr = function(o) {
       // is it x-domain
       if (o['crossOrigin'] === true) {
         var xhr = win[xmlHttpRequest] ? new XMLHttpRequest() : null
         if (xhr && 'withCredentials' in xhr) {
           return xhr
         } else if (win[xDomainRequest]) {
           return new XDomainRequest()
         } else {
           throw new Error('Browser does not support cross-origin requests')
         }
       } else if (win[xmlHttpRequest]) {
         return new XMLHttpRequest()
       } else {
         return new ActiveXObject('Microsoft.XMLHTTP')
       }
     }
   , globalSetupOptions = {
       dataFilter: function (data) {
         return data
       }
     }
 function succeed(r) {
   var protocol = protocolRe.exec(r.url);
   protocol = (protocol && protocol[1]) || window.location.protocol;
   return httpsRe.test(protocol) ? twoHundo.test(r.request.status) : !!r.request.response;
 }
 function handleReadyState(r, success, error) {
   return function () {
     // use _aborted to mitigate against IE err c00c023f
     // (can't read props on aborted request objects)
     if (r._aborted) return error(r.request)
     if (r._timedOut) return error(r.request, 'Request is aborted: timeout')
     if (r.request && r.request[readyState] == 4) {
       r.request.onreadystatechange = noop
       if (succeed(r)) success(r.request)
       else
         error(r.request)
     }
   }
 }
 function setHeaders(http, o) {
   var headers = o['headers'] || {}
     , h
   headers['Accept'] = headers['Accept']
     || defaultHeaders['accept'][o['type']]
     || defaultHeaders['accept']['*']
   var isAFormData = typeof FormData === 'function' && (o['data'] instanceof FormData);
   // breaks cross-origin requests with legacy browsers
   if (!o['crossOrigin'] && !headers[requestedWith]) headers[requestedWith] = defaultHeaders['requestedWith']
   if (!headers[contentType] && !isAFormData) headers[contentType] = o['contentType'] || defaultHeaders['contentType']
   for (h in headers)
     headers.hasOwnProperty(h) && 'setRequestHeader' in http && http.setRequestHeader(h, headers[h])
 }
 function setCredentials(http, o) {
   if (typeof o['withCredentials'] !== 'undefined' && typeof http.withCredentials !== 'undefined') {
     http.withCredentials = !!o['withCredentials']
   }
 }
 function generalCallback(data) {
   lastValue = data
 }
 function urlappend (url, s) {
   return url + (/\?/.test(url) ? '&' : '?') + s
 }
 function handleJsonp(o, fn, err, url) {
   var reqId = uniqid++
     , cbkey = o['jsonpCallback'] || 'callback' // the 'callback' key
     , cbval = o['jsonpCallbackName'] || reqwest.getcallbackPrefix(reqId)
     , cbreg = new RegExp('((^|\\?|&)' + cbkey + ')=([^&]+)')
     , match = url.match(cbreg)
     , script = doc.createElement('script')
     , loaded = 0
     , isIE10 = navigator.userAgent.indexOf('MSIE 10.0') !== -1
   if (match) {
     if (match[3] === '?') {
       url = url.replace(cbreg, '$1=' + cbval) // wildcard callback func name
     } else {
       cbval = match[3] // provided callback func name
     }
   } else {
     url = urlappend(url, cbkey + '=' + cbval) // no callback details, add 'em
   }
   win[cbval] = generalCallback
   script.type = 'text/javascript'
   script.src = url
   script.async = true
   if (typeof script.onreadystatechange !== 'undefined' && !isIE10) {
     // need this for IE due to out-of-order onreadystatechange(), binding script
     // execution to an event listener gives us control over when the script
     // is executed. See http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
     script.htmlFor = script.id = '_reqwest_' + reqId
   }
   script.onload = script.onreadystatechange = function () {
     if ((script[readyState] && script[readyState] !== 'complete' && script[readyState] !== 'loaded') || loaded) {
       return false
     }
     script.onload = script.onreadystatechange = null
     script.onclick && script.onclick()
     // Call the user callback with the last value stored and clean up values and scripts.
     fn(lastValue)
     lastValue = undefined
     head.removeChild(script)
     loaded = 1
   }
   // Add the script to the DOM head
   head.appendChild(script)
   // Enable JSONP timeout
   return {
     abort: function () {
       script.onload = script.onreadystatechange = null
       err({}, 'Request is aborted: timeout', {})
       lastValue = undefined
       head.removeChild(script)
       loaded = 1
     }
   }
 }
 function getRequest(fn, err) {
   var o = this.o
     , method = (o['method'] || 'GET').toUpperCase()
     , url = typeof o === 'string' ? o : o['url']
     // convert non-string objects to query-string form unless o['processData'] is false
     , data = (o['processData'] !== false && o['data'] && typeof o['data'] !== 'string')
       ? reqwest.toQueryString(o['data'])
       : (o['data'] || null)
     , http
     , sendWait = false
   // if we're working on a GET request and we have data then we should append
   // query string to end of URL and not post data
   if ((o['type'] == 'jsonp' || method == 'GET') && data) {
     url = urlappend(url, data)
     data = null
   }
   if (o['type'] == 'jsonp') return handleJsonp(o, fn, err, url)
   // get the xhr from the factory if passed
   // if the factory returns null, fall-back to ours
   http = (o.xhr && o.xhr(o)) || xhr(o)
   http.open(method, url, o['async'] === false ? false : true)
   setHeaders(http, o)
   setCredentials(http, o)
   if (win[xDomainRequest] && http instanceof win[xDomainRequest]) {
       http.onload = fn
       http.onerror = err
       // NOTE: see
       // http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/30ef3add-767c-4436-b8a9-f1ca19b4812e
       http.onprogress = function() {}
       sendWait = true
   } else {
     http.onreadystatechange = handleReadyState(this, fn, err)
   }
   o['before'] && o['before'](http)
   if (sendWait) {
     setTimeout(function () {
       http.send(data)
     }, 200)
   } else {
     http.send(data)
   }
   return http
 }
 function Reqwest(o, fn) {
   this.o = o
   this.fn = fn
   init.apply(this, arguments)
 }
 function setType(header) {
   // json, javascript, text/plain, text/html, xml
   if (header.match('json')) return 'json'
   if (header.match('javascript')) return 'js'
   if (header.match('text')) return 'html'
   if (header.match('xml')) return 'xml'
 }
 function init(o, fn) {
   this.url = typeof o == 'string' ? o : o['url']
   this.timeout = null
   // whether request has been fulfilled for purpose
   // of tracking the Promises
   this._fulfilled = false
   // success handlers
   this._successHandler = function(){}
   this._fulfillmentHandlers = []
   // error handlers
   this._errorHandlers = []
   // complete (both success and fail) handlers
   this._completeHandlers = []
   this._erred = false
   this._responseArgs = {}
   var self = this
   fn = fn || function () {}
   if (o['timeout']) {
     this.timeout = setTimeout(function () {
       timedOut()
     }, o['timeout'])
   }
   if (o['success']) {
     this._successHandler = function () {
       o['success'].apply(o, arguments)
     }
   }
   if (o['error']) {
     this._errorHandlers.push(function () {
       o['error'].apply(o, arguments)
     })
   }
   if (o['complete']) {
     this._completeHandlers.push(function () {
       o['complete'].apply(o, arguments)
     })
   }
   function complete (resp) {
     o['timeout'] && clearTimeout(self.timeout)
     self.timeout = null
     while (self._completeHandlers.length > 0) {
       self._completeHandlers.shift()(resp)
     }
   }
   function success (resp) {
     var type = o['type'] || resp && setType(resp.getResponseHeader('Content-Type')) // resp can be undefined in IE
     resp = (type !== 'jsonp') ? self.request : resp
     // use global data filter on response text
     var filteredResponse = globalSetupOptions.dataFilter(resp.responseText, type)
       , r = filteredResponse
     try {
       resp.responseText = r
     } catch (e) {
       // can't assign this in IE<=8, just ignore
     }
     if (r) {
       switch (type) {
       case 'json':
         try {
           resp = win.JSON ? win.JSON.parse(r) : eval('(' + r + ')')
         } catch (err) {
           return error(resp, 'Could not parse JSON in response', err)
         }
         break
       case 'js':
         resp = eval(r)
         break
       case 'html':
         resp = r
         break
       case 'xml':
         resp = resp.responseXML
             && resp.responseXML.parseError // IE trololo
             && resp.responseXML.parseError.errorCode
             && resp.responseXML.parseError.reason
           ? null
           : resp.responseXML
         break
       }
     }
     self._responseArgs.resp = resp
     self._fulfilled = true
     fn(resp)
     self._successHandler(resp)
     while (self._fulfillmentHandlers.length > 0) {
       resp = self._fulfillmentHandlers.shift()(resp)
     }
     complete(resp)
   }
   function timedOut() {
     self._timedOut = true
     self.request.abort()      
   }
   function error(resp, msg, t) {
     resp = self.request
     self._responseArgs.resp = resp
     self._responseArgs.msg = msg
     self._responseArgs.t = t
     self._erred = true
     while (self._errorHandlers.length > 0) {
       self._errorHandlers.shift()(resp, msg, t)
     }
     complete(resp)
   }
   this.request = getRequest.call(this, success, error)
 }
 Reqwest.prototype = {
   abort: function () {
     this._aborted = true
     this.request.abort()
   }
 , retry: function () {
     init.call(this, this.o, this.fn)
   }
   /**
    * Small deviation from the Promises A CommonJs specification
    * http://wiki.commonjs.org/wiki/Promises/A
    */
   /**
    * `then` will execute upon successful requests
    */
 , then: function (success, fail) {
     success = success || function () {}
     fail = fail || function () {}
     if (this._fulfilled) {
       this._responseArgs.resp = success(this._responseArgs.resp)
     } else if (this._erred) {
       fail(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
     } else {
       this._fulfillmentHandlers.push(success)
       this._errorHandlers.push(fail)
     }
     return this
   }
   /**
    * `always` will execute whether the request succeeds or fails
    */
 , always: function (fn) {
     if (this._fulfilled || this._erred) {
       fn(this._responseArgs.resp)
     } else {
       this._completeHandlers.push(fn)
     }
     return this
   }
   /**
    * `fail` will execute when the request fails
    */
 , fail: function (fn) {
     if (this._erred) {
       fn(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
     } else {
       this._errorHandlers.push(fn)
     }
     return this
   }
 , 'catch': function (fn) {
     return this.fail(fn)
   }
 }
 function reqwest(o, fn) {
   return new Reqwest(o, fn)
 }
 // normalize newline variants according to spec -> CRLF
 function normalize(s) {
   return s ? s.replace(/\r?\n/g, '\r\n') : 
 }
 function serial(el, cb) {
   var n = el.name
     , t = el.tagName.toLowerCase()
     , optCb = function (o) {
         // IE gives value="" even where there is no value attribute
         // 'specified' ref: http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-862529273
         if (o && !o['disabled'])
           cb(n, normalize(o['attributes']['value'] && o['attributes']['value']['specified'] ? o['value'] : o['text']))
       }
     , ch, ra, val, i
   // don't serialize elements that are disabled or without a name
   if (el.disabled || !n) return
   switch (t) {
   case 'input':
     if (!/reset|button|image|file/i.test(el.type)) {
       ch = /checkbox/i.test(el.type)
       ra = /radio/i.test(el.type)
       val = el.value
       // WebKit gives us "" instead of "on" if a checkbox has no value, so correct it here
       ;(!(ch || ra) || el.checked) && cb(n, normalize(ch && val ===  ? 'on' : val))
     }
     break
   case 'textarea':
     cb(n, normalize(el.value))
     break
   case 'select':
     if (el.type.toLowerCase() === 'select-one') {
       optCb(el.selectedIndex >= 0 ? el.options[el.selectedIndex] : null)
     } else {
       for (i = 0; el.length && i < el.length; i++) {
         el.options[i].selected && optCb(el.options[i])
       }
     }
     break
   }
 }
 // collect up all form elements found from the passed argument elements all
 // the way down to child elements; pass a '<form>' or form fields.
 // called with 'this'=callback to use for serial() on each element
 function eachFormElement() {
   var cb = this
     , e, i
     , serializeSubtags = function (e, tags) {
         var i, j, fa
         for (i = 0; i < tags.length; i++) {
           fa = e[byTag](tags[i])
           for (j = 0; j < fa.length; j++) serial(fa[j], cb)
         }
       }
   for (i = 0; i < arguments.length; i++) {
     e = arguments[i]
     if (/input|select|textarea/i.test(e.tagName)) serial(e, cb)
     serializeSubtags(e, [ 'input', 'select', 'textarea' ])
   }
 }
 // standard query string style serialization
 function serializeQueryString() {
   return reqwest.toQueryString(reqwest.serializeArray.apply(null, arguments))
 }
 // { 'name': 'value', ... } style serialization
 function serializeHash() {
   var hash = {}
   eachFormElement.apply(function (name, value) {
     if (name in hash) {
       hash[name] && !isArray(hash[name]) && (hash[name] = [hash[name]])
       hash[name].push(value)
     } else hash[name] = value
   }, arguments)
   return hash
 }
 // [ { name: 'name', value: 'value' }, ... ] style serialization
 reqwest.serializeArray = function () {
   var arr = []
   eachFormElement.apply(function (name, value) {
     arr.push({name: name, value: value})
   }, arguments)
   return arr
 }
 reqwest.serialize = function () {
   if (arguments.length === 0) return 
   var opt, fn
     , args = Array.prototype.slice.call(arguments, 0)
   opt = args.pop()
   opt && opt.nodeType && args.push(opt) && (opt = null)
   opt && (opt = opt.type)
   if (opt == 'map') fn = serializeHash
   else if (opt == 'array') fn = reqwest.serializeArray
   else fn = serializeQueryString
   return fn.apply(null, args)
 }
 reqwest.toQueryString = function (o, trad) {
   var prefix, i
     , traditional = trad || false
     , s = []
     , enc = encodeURIComponent
     , add = function (key, value) {
         // If value is a function, invoke it and return its value
         value = ('function' === typeof value) ? value() : (value == null ?  : value)
         s[s.length] = enc(key) + '=' + enc(value)
       }
   // If an array was passed in, assume that it is an array of form elements.
   if (isArray(o)) {
     for (i = 0; o && i < o.length; i++) add(o[i]['name'], o[i]['value'])
   } else {
     // If traditional, encode the "old" way (the way 1.3.2 or older
     // did it), otherwise encode params recursively.
     for (prefix in o) {
       if (o.hasOwnProperty(prefix)) buildParams(prefix, o[prefix], traditional, add)
     }
   }
   // spaces should be + according to spec
   return s.join('&').replace(/%20/g, '+')
 }
 function buildParams(prefix, obj, traditional, add) {
   var name, i, v
     , rbracket = /\[\]$/
   if (isArray(obj)) {
     // Serialize array item.
     for (i = 0; obj && i < obj.length; i++) {
       v = obj[i]
       if (traditional || rbracket.test(prefix)) {
         // Treat each array item as a scalar.
         add(prefix, v)
       } else {
         buildParams(prefix + '[' + (typeof v === 'object' ? i : ) + ']', v, traditional, add)
       }
     }
   } else if (obj && obj.toString() === '[object Object]') {
     // Serialize object item.
     for (name in obj) {
       buildParams(prefix + '[' + name + ']', obj[name], traditional, add)
     }
   } else {
     // Serialize scalar item.
     add(prefix, obj)
   }
 }
 reqwest.getcallbackPrefix = function () {
   return callbackPrefix
 }
 // jQuery and Zepto compatibility, differences can be remapped here so you can call
 // .ajax.compat(options, callback)
 reqwest.compat = function (o, fn) {
   if (o) {
     o['type'] && (o['method'] = o['type']) && delete o['type']
     o['dataType'] && (o['type'] = o['dataType'])
     o['jsonpCallback'] && (o['jsonpCallbackName'] = o['jsonpCallback']) && delete o['jsonpCallback']
     o['jsonp'] && (o['jsonpCallback'] = o['jsonp'])
   }
   return new Reqwest(o, fn)
 }
 reqwest.ajaxSetup = function (options) {
   options = options || {}
   for (var k in options) {
     globalSetupOptions[k] = options[k]
   }
 }
 return reqwest

});

},{}],28:[function(_dereq_,module,exports){

'use strict';

var p5 = _dereq_('./core/core'); _dereq_('./color/p5.Color'); _dereq_('./core/p5.Element'); _dereq_('./typography/p5.Font'); _dereq_('./core/p5.Graphics'); _dereq_('./core/p5.Renderer2D');

_dereq_('./image/p5.Image'); _dereq_('./math/p5.Vector'); _dereq_('./io/p5.TableRow'); _dereq_('./io/p5.Table'); _dereq_('./io/p5.XML');

_dereq_('./color/creating_reading'); _dereq_('./color/setting'); _dereq_('./core/constants'); _dereq_('./utilities/conversion'); _dereq_('./utilities/array_functions'); _dereq_('./utilities/string_functions'); _dereq_('./core/environment'); _dereq_('./image/image'); _dereq_('./image/loading_displaying'); _dereq_('./image/pixels'); _dereq_('./io/files'); _dereq_('./events/keyboard'); _dereq_('./events/acceleration'); //john _dereq_('./events/mouse'); _dereq_('./utilities/time_date'); _dereq_('./events/touch'); _dereq_('./math/math'); _dereq_('./math/calculation'); _dereq_('./math/random'); _dereq_('./math/noise'); _dereq_('./math/trigonometry'); _dereq_('./core/rendering'); _dereq_('./core/2d_primitives');

_dereq_('./core/attributes'); _dereq_('./core/curves'); _dereq_('./core/vertex'); _dereq_('./core/structure'); _dereq_('./core/transform'); _dereq_('./typography/attributes'); _dereq_('./typography/loading_displaying');

_dereq_('./webgl/p5.RendererGL'); _dereq_('./webgl/p5.Geometry'); _dereq_('./webgl/p5.RendererGL.Retained'); _dereq_('./webgl/p5.RendererGL.Immediate'); _dereq_('./webgl/primitives'); _dereq_('./webgl/loading'); _dereq_('./webgl/p5.Matrix'); _dereq_('./webgl/material'); _dereq_('./webgl/light'); _dereq_('./webgl/shader'); _dereq_('./webgl/camera'); _dereq_('./webgl/interaction');

/**

* _globalInit
*
* TODO: ???
* if sketch is on window
* assume "global" mode
* and instantiate p5 automatically
* otherwise do nothing
*
* @return {Undefined}
*/

var _globalInit = function() {

 if (!window.PHANTOMJS && !window.mocha) {
   // If there is a setup or draw function on the window
   // then instantiate p5 in "global" mode
   if(((window.setup && typeof window.setup === 'function') ||
      (window.draw && typeof window.draw === 'function')) &&
      !p5.instance) {
     new p5();
   }
 }

};

// TODO: ??? if (document.readyState === 'complete') {

 _globalInit();

} else {

 window.addEventListener('load', _globalInit , false);

}

module.exports = p5;

},{"./color/creating_reading":30,"./color/p5.Color":31,"./color/setting":32,"./core/2d_primitives":33,"./core/attributes":34,"./core/constants":36,"./core/core":37,"./core/curves":38,"./core/environment":39,"./core/p5.Element":41,"./core/p5.Graphics":42,"./core/p5.Renderer2D":44,"./core/rendering":45,"./core/structure":47,"./core/transform":48,"./core/vertex":49,"./events/acceleration":50,"./events/keyboard":51,"./events/mouse":52,"./events/touch":53,"./image/image":55,"./image/loading_displaying":56,"./image/p5.Image":57,"./image/pixels":58,"./io/files":59,"./io/p5.Table":60,"./io/p5.TableRow":61,"./io/p5.XML":62,"./math/calculation":63,"./math/math":64,"./math/noise":65,"./math/p5.Vector":66,"./math/random":68,"./math/trigonometry":69,"./typography/attributes":70,"./typography/loading_displaying":71,"./typography/p5.Font":72,"./utilities/array_functions":73,"./utilities/conversion":74,"./utilities/string_functions":75,"./utilities/time_date":76,"./webgl/camera":77,"./webgl/interaction":78,"./webgl/light":79,"./webgl/loading":80,"./webgl/material":81,"./webgl/p5.Geometry":82,"./webgl/p5.Matrix":83,"./webgl/p5.RendererGL":86,"./webgl/p5.RendererGL.Immediate":84,"./webgl/p5.RendererGL.Retained":85,"./webgl/primitives":87,"./webgl/shader":88}],29:[function(_dereq_,module,exports){ /**

* module Conversion
* submodule Color Conversion
* @for p5
* @requires core
*/

'use strict';

/**

* Conversions adapted from <http://www.easyrgb.com/math.html>.
*
* In these functions, hue is always in the range [0,1); all other components
* are in the range [0,1]. 'Brightness' and 'value' are used interchangeably.
*/

var p5 = _dereq_('../core/core'); p5.ColorConversion = {};

/**

* Convert an HSBA array to HSLA.
*/

p5.ColorConversion._hsbaToHSLA = function(hsba) {

 var hue = hsba[0];
 var sat = hsba[1];
 var val = hsba[2];
 // Calculate lightness.
 var li = (2 - sat) * val / 2;
 // Convert saturation.
 if (li !== 0) {
   if (li === 1) {
     sat = 0;
   } else if (li < 0.5) {
     sat = sat / (2 - sat);
   } else {
     sat = sat * val / (2 - li * 2);
   }
 }
 // Hue and alpha stay the same.
 return [hue, sat, li, hsba[3]];

};

/**

* Convert an HSBA array to RGBA.
*/

p5.ColorConversion._hsbaToRGBA = function(hsba) {

 var hue = hsba[0] * 6;  // We will split hue into 6 sectors.
 var sat = hsba[1];
 var val = hsba[2];
 var RGBA = [];
 if (sat === 0) {
   RGBA = [val, val, val, hsba[3]];  // Return early if grayscale.
 } else {
   var sector = Math.floor(hue);
   var tint1 = val * (1 - sat);
   var tint2 = val * (1 - sat * (hue - sector));
   var tint3 = val * (1 - sat * (1 + sector - hue));
   var red, green, blue;
   if (sector === 1) {  // Yellow to green.
     red = tint2;
     green = val;
     blue = tint1;
   } else if (sector === 2) {  // Green to cyan.
     red = tint1;
     green = val;
     blue = tint3;
   } else if (sector === 3) {  // Cyan to blue.
     red = tint1;
     green = tint2;
     blue = val;
   } else if (sector === 4) {  // Blue to magenta.
     red = tint3;
     green = tint1;
     blue = val;
   } else if (sector === 5) {  // Magenta to red.
     red = val;
     green = tint1;
     blue = tint2;
   } else {  // Red to yellow (sector could be 0 or 6).
     red = val;
     green = tint3;
     blue = tint1;
   }
   RGBA = [red, green, blue, hsba[3]];
 }
 return RGBA;

};

/**

* Convert an HSLA array to HSBA.
*/

p5.ColorConversion._hslaToHSBA = function(hsla) {

 var hue = hsla[0];
 var sat = hsla[1];
 var li = hsla[2];
 // Calculate brightness.
 var val;
 if (li < 0.5) {
   val = (1 + sat) * li;
 } else {
   val = li + sat - li * sat;
 }
 // Convert saturation.
 sat = 2 * (val - li) / val;
 // Hue and alpha stay the same.
 return [hue, sat, val, hsla[3]];

};

/**

* Convert an HSLA array to RGBA.
*
* We need to change basis from HSLA to something that can be more easily be
* projected onto RGBA. We will choose hue and brightness as our first two
* components, and pick a convenient third one ('zest') so that we don't need
* to calculate formal HSBA saturation.
*/

p5.ColorConversion._hslaToRGBA = function(hsla){

 var hue = hsla[0] * 6;  // We will split hue into 6 sectors.
 var sat = hsla[1];
 var li = hsla[2];
 var RGBA = [];
 if (sat === 0) {
   RGBA = [li, li, li, hsla[3]]; // Return early if grayscale.
 } else {
   // Calculate brightness.
   var val;
   if (li < 0.5) {
     val = (1 + sat) * li;
   } else {
     val = li + sat - li * sat;
   }
   // Define zest.
   var zest = 2 * li - val;
   // Implement projection (project onto green by default).
   var hzvToRGB = function(hue, zest, val) {
     if (hue < 0) {  // Hue must wrap to allow projection onto red and blue.
       hue += 6;
     } else if (hue >= 6) {
       hue -= 6;
     }
     if (hue < 1) {  // Red to yellow (increasing green).
       return (zest + (val - zest) * hue);
     } else if (hue < 3) {  // Yellow to cyan (greatest green).
       return val;
     } else if (hue < 4) {  // Cyan to blue (decreasing green).
       return (zest + (val - zest) * (4 - hue));
     } else {  // Blue to red (least green).
       return zest;
     }
   };
   // Perform projections, offsetting hue as necessary.
   RGBA = [hzvToRGB(hue + 2, zest, val),
           hzvToRGB(hue    , zest, val),
           hzvToRGB(hue - 2, zest, val),
           hsla[3]];
 }
 return RGBA;

};

/**

* Convert an RGBA array to HSBA.
*/

p5.ColorConversion._rgbaToHSBA = function(rgba) {

 var red = rgba[0];
 var green = rgba[1];
 var blue = rgba[2];
 var val = Math.max(red, green, blue);
 var chroma = val - Math.min(red, green, blue);
 var hue, sat;
 if (chroma === 0) {  // Return early if grayscale.
   hue = 0;
   sat = 0;
 }
 else {
   sat = chroma / val;
   if (red === val) {  // Magenta to yellow.
     hue = (green - blue) / chroma;
   } else if (green === val) { // Yellow to cyan.
     hue = 2 + (blue - red) / chroma;
   } else if (blue === val) {  // Cyan to magenta.
     hue = 4 + (red - green) / chroma;
   }
   if (hue < 0) {  // Confine hue to the interval [0, 1).
     hue += 6;
   } else if (hue >= 6) {
     hue -= 6;
   }
 }
 return [hue / 6, sat, val, rgba[3]];

};

/**

* Convert an RGBA array to HSLA.
*/

p5.ColorConversion._rgbaToHSLA = function(rgba) {

 var red = rgba[0];
 var green = rgba[1];
 var blue = rgba[2];
 var val = Math.max(red, green, blue);
 var min = Math.min(red, green, blue);
 var li = val + min;  // We will halve this later.
 var chroma = val - min;
 var hue, sat;
 if (chroma === 0) {  // Return early if grayscale.
   hue = 0;
   sat = 0;
 } else {
   if (li < 1) {
     sat = chroma / li;
   } else {
     sat = chroma / (2 - chroma);
   }
   if (red === val) {  // Magenta to yellow.
     hue = (green - blue) / chroma;
   } else if (green === val) {  // Yellow to cyan.
     hue = 2 + (blue - red) / chroma;
   } else if (blue === val) {  // Cyan to magenta.
     hue = 4 + (red - green) / chroma;
   }
   if (hue < 0) {  // Confine hue to the interval [0, 1).
     hue += 6;
   } else if (hue >= 6) {
     hue -= 6;
   }
 }
 return [hue / 6, sat, li / 2, rgba[3]];

};

module.exports = p5.ColorConversion;

},{"../core/core":37}],30:[function(_dereq_,module,exports){ /**

* @module Color
* @submodule Creating & Reading
* @for p5
* @requires core
* @requires constants
*/

'use strict';

var p5 = _dereq_('../core/core'); var constants = _dereq_('../core/constants'); _dereq_('./p5.Color');

/**

* Extracts the alpha value from a color or pixel array.
*
* @method alpha
* @param {Object} obj p5.Color object or pixel array
* @example
*
* 
* noStroke();
* c = color(0, 126, 255, 102);
* fill(c);
* rect(15, 15, 35, 70);
* value = alpha(c);  // Sets 'value' to 102
* fill(value);
* rect(50, 15, 35, 70);
* 
*
*
* @alt
* Left half of canvas light blue and right half light charcoal grey.
* Left half of canvas light purple and right half a royal blue.
* Left half of canvas salmon pink and the right half white.
* Yellow rect in middle right of canvas, with 55 pixel width and height.
* Yellow ellipse in top left canvas, black ellipse in bottom right,both 80x80.
* Bright fuschia rect in middle of canvas, 60 pixel width and height.
* Two bright green rects on opposite sides of the canvas, both 45x80.
* Four blue rects in each corner of the canvas, each are 35x35.
* Bright sea green rect on left and darker rect on right of canvas, both 45x80.
* Dark green rect on left and light green rect on right of canvas, both 45x80.
* Dark blue rect on left and light teal rect on right of canvas, both 45x80.
* blue rect on left and green on right, both with black outlines & 35x60.
* salmon pink rect on left and black on right, both 35x60.
* 4 rects, tan, brown, brownish purple and purple, with white outlines & 20x60.
* light pastel green rect on left and dark grey rect on right, both 35x60.
* yellow rect on left and red rect on right, both with black outlines & 35x60.
* grey canvas
* deep pink rect on left and grey rect on right, both 35x60.
*/

p5.prototype.alpha = function(c) {

 if (c instanceof p5.Color || c instanceof Array) {
   return this.color(c)._getAlpha();
 } else {
   throw new Error('Needs p5.Color or pixel array as argument.');
 }

};

/**

* Extracts the blue value from a color or pixel array.
*
* @method blue
* @param {Object} obj p5.Color object or pixel array
* @example
*
* 
* c = color(175, 100, 220);  // Define color 'c'
* fill(c);  // Use color variable 'c' as fill color
* rect(15, 20, 35, 60);  // Draw left rectangle
*
* blueValue = blue(c);  // Get blue in 'c'
* print(blueValue);  // Prints "220.0"
* fill(0, 0, blueValue);  // Use 'blueValue' in new fill
* rect(50, 20, 35, 60);  // Draw right rectangle
* 
*
*
* @alt
* Left half of canvas light purple and right half a royal blue.
*
*/

p5.prototype.blue = function(c) {

 if (c instanceof p5.Color || c instanceof Array) {
   return this.color(c)._getBlue();
 } else {
   throw new Error('Needs p5.Color or pixel array as argument.');
 }

};

/**

* Extracts the HSB brightness value from a color or pixel array.
*
* @method brightness
* @param {Object} color p5.Color object or pixel array
* @example
*
* 
* noStroke();
* colorMode(HSB, 255);
* c = color(0, 126, 255);
* fill(c);
* rect(15, 20, 35, 60);
* value = brightness(c);  // Sets 'value' to 255
* fill(value);
* rect(50, 20, 35, 60);
* 
*
*
* @alt
* Left half of canvas salmon pink and the right half white.
*
*/

p5.prototype.brightness = function(c) {

 if (c instanceof p5.Color || c instanceof Array) {
   return this.color(c)._getBrightness();
 } else {
   throw new Error('Needs p5.Color or pixel array as argument.');
 }

};

/**

* Creates colors for storing in variables of the color datatype. The
* parameters are interpreted as RGB or HSB values depending on the
* current colorMode(). The default mode is RGB values from 0 to 255
* and, therefore, the function call color(255, 204, 0) will return a
* bright yellow color.
* 

* Note that if only one value is provided to color(), it will be interpreted * as a grayscale value. Add a second value, and it will be used for alpha * transparency. When three values are specified, they are interpreted as * either RGB or HSB values. Adding a fourth value applies alpha * transparency. If a single string parameter is provided it will be * interpreted as a CSS-compatible color string. * * Colors are stored as Numbers or Arrays. * * @method color * @param {Number|String} gray number specifying value between white * and black. * @param {Number} [alpha] alpha value relative to current color range * (default is 0-100) * @return {Array} resulting color * * @example
*
* 
* var c = color(255, 204, 0);  // Define color 'c'
* fill(c);  // Use color variable 'c' as fill color
* noStroke();  // Don't draw a stroke around shapes
* rect(30, 20, 55, 55);  // Draw rectangle
* 
*
*
*
* 
* var c = color(255, 204, 0);  // Define color 'c'
* fill(c);  // Use color variable 'c' as fill color
* noStroke();  // Don't draw a stroke around shapes
* ellipse(25, 25, 80, 80);  // Draw left circle
*
* // Using only one value with color()
* // generates a grayscale value.
* var c = color(65);  // Update 'c' with grayscale value
* fill(c);  // Use updated 'c' as fill color
* ellipse(75, 75, 80, 80);  // Draw right circle
* 
*
*
*
* 
* // Named SVG & CSS colors may be used,
* var c = color('magenta');
* fill(c);  // Use 'c' as fill color
* noStroke();  // Don't draw a stroke around shapes
* rect(20, 20, 60, 60);  // Draw rectangle
* 
*
*
*
* 
* // as can hex color codes:
* noStroke();  // Don't draw a stroke around shapes
* var c = color('#0f0');
* fill(c);  // Use 'c' as fill color
* rect(0, 10, 45, 80);  // Draw rectangle
*
* c = color('#00ff00');
* fill(c);  // Use updated 'c' as fill color
* rect(55, 10, 45, 80);  // Draw rectangle
* 
*
*
*
* 
* // RGB and RGBA color strings are also supported:
* // these all set to the same color (solid blue)
* var c;
* noStroke();  // Don't draw a stroke around shapes
* c = color('rgb(0,0,255)');
* fill(c); // Use 'c' as fill color
* rect(10, 10, 35, 35);  // Draw rectangle
*
* c = color('rgb(0%, 0%, 100%)');
* fill(c); // Use updated 'c' as fill color
* rect(55, 10, 35, 35);  // Draw rectangle
*
* c = color('rgba(0, 0, 255, 1)');
* fill(c); // Use updated 'c' as fill color
* rect(10, 55, 35, 35);  // Draw rectangle
*
* c = color('rgba(0%, 0%, 100%, 1)');
* fill(c); // Use updated 'c' as fill color
* rect(55, 55, 35, 35);  // Draw rectangle
* 
*
*
*
* 
* // HSL color is also supported and can be specified
* // by value
* var c;
* noStroke();  // Don't draw a stroke around shapes
* c = color('hsl(160, 100%, 50%)');
* fill(c);  // Use 'c' as fill color
* rect(0, 10, 45, 80);  // Draw rectangle
*
* c = color('hsla(160, 100%, 50%, 0.5)');
* fill(c); // Use updated 'c' as fill color
* rect(55, 10, 45, 80);  // Draw rectangle
* 
*
*
*
* 
* // HSB color is also supported and can be specified
* // by value
* var c;
* noStroke();  // Don't draw a stroke around shapes
* c = color('hsb(160, 100%, 50%)');
* fill(c);  // Use 'c' as fill color
* rect(0, 10, 45, 80);  // Draw rectangle
*
* c = color('hsba(160, 100%, 50%, 0.5)');
* fill(c); // Use updated 'c' as fill color
* rect(55, 10, 45, 80);  // Draw rectangle
* 
*
*
*
* 
* var c;  // Declare color 'c'
* noStroke();  // Don't draw a stroke around shapes
*
* // If no colorMode is specified, then the
* // default of RGB with scale of 0-255 is used.
* c = color(50, 55, 100);  // Create a color for 'c'
* fill(c);  // Use color variable 'c' as fill color
* rect(0, 10, 45, 80);  // Draw left rect
*
* colorMode(HSB, 100);  // Use HSB with scale of 0-100
* c = color(50, 55, 100);  // Update 'c' with new color
* fill(c);  // Use updated 'c' as fill color
* rect(55, 10, 45, 80);  // Draw right rect
* 
*
*
* @alt
* Yellow rect in middle right of canvas, with 55 pixel width and height.
* Yellow ellipse in top left of canvas, black ellipse in bottom right,both 80x80.
* Bright fuschia rect in middle of canvas, 60 pixel width and height.
* Two bright green rects on opposite sides of the canvas, both 45x80.
* Four blue rects in each corner of the canvas, each are 35x35.
* Bright sea green rect on left and darker rect on right of canvas, both 45x80.
* Dark green rect on left and lighter green rect on right of canvas, both 45x80.
* Dark blue rect on left and light teal rect on right of canvas, both 45x80.
*
*/

/**

* @method color
* @param  {Number|String} v1      red or hue value relative to
*                                 the current color range, or a color string
* @param  {Number}        v2      green or saturation value
*                                 relative to the current color range
* @param  {Number}        v3      blue or brightness value
*                                 relative to the current color range
* @param  {Number}        [alpha]
*/

p5.prototype.color = function() {

 if (arguments[0] instanceof p5.Color) {
   return arguments[0];  // Do nothing if argument is already a color object.
 } else if (arguments[0] instanceof Array) {
   if (this instanceof p5.Renderer) {
     return new p5.Color(this, arguments[0]);
   } else {
     return new p5.Color(this._renderer, arguments[0]);
   }
 } else {
   if (this instanceof p5.Renderer) {
     return new p5.Color(this, arguments);
   } else {
     return new p5.Color(this._renderer, arguments);
   }
 }

};

/**

* Extracts the green value from a color or pixel array.
*
* @method green
* @param {Object} color p5.Color object or pixel array
* @example
*
* 
* c = color(20, 75, 200);  // Define color 'c'
* fill(c);  // Use color variable 'c' as fill color
* rect(15, 20, 35, 60);  // Draw left rectangle
*
* greenValue = green(c);  // Get green in 'c'
* print(greenValue);  // Print "75.0"
* fill(0, greenValue, 0);  // Use 'greenValue' in new fill
* rect(50, 20, 35, 60);  // Draw right rectangle
* 
*
*
* @alt
* blue rect on left and green on right, both with black outlines & 35x60.
*
*/

p5.prototype.green = function(c) {

 if (c instanceof p5.Color || c instanceof Array) {
   return this.color(c)._getGreen();
 } else {
   throw new Error('Needs p5.Color or pixel array as argument.');
 }

};

/**

* Extracts the hue value from a color or pixel array.
*
* Hue exists in both HSB and HSL. This function will return the
* HSB-normalized hue when supplied with an HSB color object (or when supplied
* with a pixel array while the color mode is HSB), but will default to the
* HSL-normalized hue otherwise. (The values will only be different if the
* maximum hue setting for each system is different.)
*
* @method hue
* @param {Object} color p5.Color object or pixel array
* @example
*
* 
* noStroke();
* colorMode(HSB, 255);
* c = color(0, 126, 255);
* fill(c);
* rect(15, 20, 35, 60);
* value = hue(c);  // Sets 'value' to "0"
* fill(value);
* rect(50, 20, 35, 60);
* 
*
*
* @alt
* salmon pink rect on left and black on right, both 35x60.
*
*/

p5.prototype.hue = function(c) {

 if (c instanceof p5.Color || c instanceof Array) {
   return this.color(c)._getHue();
 } else {
   throw new Error('Needs p5.Color or pixel array as argument.');
 }

};

/**

* Blends two colors to find a third color somewhere between them. The amt
* parameter is the amount to interpolate between the two values where 0.0
* equal to the first color, 0.1 is very near the first color, 0.5 is halfway
* in between, etc. An amount below 0 will be treated as 0. Likewise, amounts
* above 1 will be capped at 1. This is different from the behavior of lerp(),
* but necessary because otherwise numbers outside the range will produce
* strange and unexpected colors.
* 

* The way that colours are interpolated depends on the current color mode. * * @method lerpColor * @param {Array/Number} c1 interpolate from this color * @param {Array/Number} c2 interpolate to this color * @param {Number} amt number between 0 and 1 * @return {Array/Number} interpolated color * @example
*
* 
* colorMode(RGB);
* stroke(255);
* background(51);
* from = color(218, 165, 32);
* to = color(72, 61, 139);
* colorMode(RGB);  // Try changing to HSB.
* interA = lerpColor(from, to, .33);
* interB = lerpColor(from, to, .66);
* fill(from);
* rect(10, 20, 20, 60);
* fill(interA);
* rect(30, 20, 20, 60);
* fill(interB);
* rect(50, 20, 20, 60);
* fill(to);
* rect(70, 20, 20, 60);
* 
*
*
* @alt
* 4 rects one tan, brown, brownish purple, purple, with white outlines & 20x60
*
*/

p5.prototype.lerpColor = function(c1, c2, amt) {

 var mode = this._renderer._colorMode;
 var maxes = this._renderer._colorMaxes;
 var l0, l1, l2, l3;
 var fromArray, toArray;
 if (mode === constants.RGB) {
   fromArray = c1.levels.map(function(level) {
     return level / 255;
   });
   toArray = c2.levels.map(function(level) {
     return level / 255;
   });
 } else if (mode === constants.HSB) {
   c1._getBrightness();  // Cache hsba so it definitely exists.
   c2._getBrightness();
   fromArray = c1.hsba;
   toArray = c2.hsba;
 } else if (mode === constants.HSL) {
   c1._getLightness();  // Cache hsla so it definitely exists.
   c2._getLightness();
   fromArray = c1.hsla;
   toArray = c2.hsla;
 } else {
   throw new Error (mode + 'cannot be used for interpolation.');
 }
 // Prevent extrapolation.
 amt = Math.max(Math.min(amt, 1), 0);
 // Perform interpolation.
 l0 = this.lerp(fromArray[0], toArray[0], amt);
 l1 = this.lerp(fromArray[1], toArray[1], amt);
 l2 = this.lerp(fromArray[2], toArray[2], amt);
 l3 = this.lerp(fromArray[3], toArray[3], amt);
 // Scale components.
 l0 *= maxes[mode][0];
 l1 *= maxes[mode][1];
 l2 *= maxes[mode][2];
 l3 *= maxes[mode][3];
 return this.color(l0, l1, l2, l3);

};

/**

* Extracts the HSL lightness value from a color or pixel array.
*
* @method lightness
* @param {Object} color p5.Color object or pixel array
* @example
*
* 
* noStroke();
* colorMode(HSL);
* c = color(156, 100, 50, 1);
* fill(c);
* rect(15, 20, 35, 60);
* value = lightness(c);  // Sets 'value' to 50
* fill(value);
* rect(50, 20, 35, 60);
* 
*
*
* @alt
* light pastel green rect on left and dark grey rect on right, both 35x60.
*
*/

p5.prototype.lightness = function(c) {

 if (c instanceof p5.Color || c instanceof Array) {
   return this.color(c)._getLightness();
 } else {
   throw new Error('Needs p5.Color or pixel array as argument.');
 }

};

/**

* Extracts the red value from a color or pixel array.
*
* @method red
* @param {Object} obj p5.Color object or pixel array
* @example
*
* 
* c = color(255, 204, 0);  // Define color 'c'
* fill(c);  // Use color variable 'c' as fill color
* rect(15, 20, 35, 60);  // Draw left rectangle
*
* redValue = red(c);  // Get red in 'c'
* print(redValue);  // Print "255.0"
* fill(redValue, 0, 0);  // Use 'redValue' in new fill
* rect(50, 20, 35, 60);  // Draw right rectangle
* 
*
*
*
* 
* colorMode(RGB, 255);
* var c = color(127, 255, 0);
* colorMode(RGB, 1);
* var myColor = red(c);
* print(myColor);
* 
*
*
* @alt
* yellow rect on left and red rect on right, both with black outlines and 35x60.
* grey canvas
*/

p5.prototype.red = function(c) {

 if (c instanceof p5.Color || c instanceof Array) {
   return this.color(c)._getRed();
 } else {
   throw new Error('Needs p5.Color or pixel array as argument.');
 }

};

/**

* Extracts the saturation value from a color or pixel array.
*
* Saturation is scaled differently in HSB and HSL. This function will return
* the HSB saturation when supplied with an HSB color object (or when supplied
* with a pixel array while the color mode is HSB), but will default to the
* HSL saturation otherwise.
*
* @method saturation
* @param {Object} color p5.Color object or pixel array
* @example
*
* 
* noStroke();
* colorMode(HSB, 255);
* c = color(0, 126, 255);
* fill(c);
* rect(15, 20, 35, 60);
* value = saturation(c);  // Sets 'value' to 126
* fill(value);
* rect(50, 20, 35, 60);
* 
*
*
* @alt
*deep pink rect on left and grey rect on right, both 35x60.
*
*/

p5.prototype.saturation = function(c) {

 if (c instanceof p5.Color || c instanceof Array) {
   return this.color(c)._getSaturation();
 } else {
   throw new Error('Needs p5.Color or pixel array as argument.');
 }

};

module.exports = p5;

},{"../core/constants":36,"../core/core":37,"./p5.Color":31}],31:[function(_dereq_,module,exports){ /**

* @module Color
* @submodule Creating & Reading
* @for p5
* @requires core
* @requires constants
* @requires color_conversion
*/

var p5 = _dereq_('../core/core'); var constants = _dereq_('../core/constants'); var color_conversion = _dereq_('./color_conversion');

/**

* We define colors to be immutable objects. Each color stores the color mode
* and level maxes that applied at the time of its construction. These are
* used to interpret the input arguments and to format the output e.g. when
* saturation() is requested.
*
* Internally we store an array representing the ideal RGBA values in floating
* point form, normalized from 0 to 1. From this we calculate the closest
* screen color (RGBA levels from 0 to 255) and expose this to the renderer.
*
* We also cache normalized, floating point components of the color in various
* representations as they are calculated. This is done to prevent repeating a
* conversion that has already been performed.
*
* @class p5.Color
* @constructor
*/

p5.Color = function(renderer, vals) {

 // Record color mode and maxes at time of construction.
 this.mode = renderer._colorMode;
 this.maxes = renderer._colorMaxes;
 // Calculate normalized RGBA values.
 if (this.mode !== constants.RGB &&
     this.mode !== constants.HSL &&
     this.mode !== constants.HSB) {
   throw new Error(this.mode + ' is an invalid colorMode.');
 } else {
   this._array = p5.Color._parseInputs.apply(renderer, vals);
 }
 // Expose closest screen color.
 this.levels = this._array.map(function(level) {
   return Math.round(level * 255);
 });
 return this;

};

p5.Color.prototype.toString = function() {

 var a = this.levels;
 var alpha = this._array[3];  // String representation uses normalized alpha.
 return 'rgba('+a[0]+','+a[1]+','+a[2]+','+ alpha +')';

};

p5.Color.prototype._getAlpha = function() {

 return this._array[3] * this.maxes[this.mode][3];

};

p5.Color.prototype._getBlue = function() {

 return this._array[2] * this.maxes[constants.RGB][2];

};

p5.Color.prototype._getBrightness = function() {

 if (!this.hsba) {
   this.hsba = color_conversion._rgbaToHSBA(this._array);
 }
 return this.hsba[2] * this.maxes[constants.HSB][2];

};

p5.Color.prototype._getGreen = function() {

 return this._array[1] * this.maxes[constants.RGB][1];

};

/**

* Hue is the same in HSB and HSL, but the maximum value may be different.
* This function will return the HSB-normalized saturation when supplied with
* an HSB color object, but will default to the HSL-normalized saturation
* otherwise.
*/

p5.Color.prototype._getHue = function() {

 if (this.mode === constants.HSB) {
   if (!this.hsba) {
     this.hsba = color_conversion._rgbaToHSBA(this._array);
   }
   return this.hsba[0] * this.maxes[constants.HSB][0];
 } else {
   if (!this.hsla) {
     this.hsla = color_conversion._rgbaToHSLA(this._array);
   }
   return this.hsla[0] * this.maxes[constants.HSL][0];
 }

};

p5.Color.prototype._getLightness = function() {

 if (!this.hsla) {
   this.hsla = color_conversion._rgbaToHSLA(this._array);
 }
 return this.hsla[2] * this.maxes[constants.HSL][2];

};

p5.Color.prototype._getRed = function() {

 return this._array[0] * this.maxes[constants.RGB][0];

};

/**

* Saturation is scaled differently in HSB and HSL. This function will return
* the HSB saturation when supplied with an HSB color object, but will default
* to the HSL saturation otherwise.
*/

p5.Color.prototype._getSaturation = function() {

 if (this.mode === constants.HSB) {
   if (!this.hsba) {
     this.hsba = color_conversion._rgbaToHSBA(this._array);
   }
   return this.hsba[1] * this.maxes[constants.HSB][1];
 } else {
   if (!this.hsla) {
     this.hsla = color_conversion._rgbaToHSLA(this._array);
   }
   return this.hsla[1] * this.maxes[constants.HSL][1];
 }

};

/**

* CSS named colors.
*/

var namedColors = {

 aliceblue:             '#f0f8ff',
 antiquewhite:          '#faebd7',
 aqua:                  '#00ffff',
 aquamarine:            '#7fffd4',
 azure:                 '#f0ffff',
 beige:                 '#f5f5dc',
 bisque:                '#ffe4c4',
 black:                 '#000000',
 blanchedalmond:        '#ffebcd',
 blue:                  '#0000ff',
 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',
 fuchsia:               '#ff00ff',
 gainsboro:             '#dcdcdc',
 ghostwhite:            '#f8f8ff',
 gold:                  '#ffd700',
 goldenrod:             '#daa520',
 gray:                  '#808080',
 green:                 '#008000',
 greenyellow:           '#adff2f',
 grey:                  '#808080',
 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',
 lightgray:             '#d3d3d3',
 lightgreen:            '#90ee90',
 lightgrey:             '#d3d3d3',
 lightpink:             '#ffb6c1',
 lightsalmon:           '#ffa07a',
 lightseagreen:         '#20b2aa',
 lightskyblue:          '#87cefa',
 lightslategray:        '#778899',
 lightslategrey:        '#778899',
 lightsteelblue:        '#b0c4de',
 lightyellow:           '#ffffe0',
 lime:                  '#00ff00',
 limegreen:             '#32cd32',
 linen:                 '#faf0e6',
 magenta:               '#ff00ff',
 maroon:                '#800000',
 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',
 navy:                  '#000080',
 oldlace:               '#fdf5e6',
 olive:                 '#808000',
 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',
 purple:                '#800080',
 red:                   '#ff0000',
 rosybrown:             '#bc8f8f',
 royalblue:             '#4169e1',
 saddlebrown:           '#8b4513',
 salmon:                '#fa8072',
 sandybrown:            '#f4a460',
 seagreen:              '#2e8b57',
 seashell:              '#fff5ee',
 sienna:                '#a0522d',
 silver:                '#c0c0c0',
 skyblue:               '#87ceeb',
 slateblue:             '#6a5acd',
 slategray:             '#708090',
 slategrey:             '#708090',
 snow:                  '#fffafa',
 springgreen:           '#00ff7f',
 steelblue:             '#4682b4',
 tan:                   '#d2b48c',
 teal:                  '#008080',
 thistle:               '#d8bfd8',
 tomato:                '#ff6347',
 turquoise:             '#40e0d0',
 violet:                '#ee82ee',
 wheat:                 '#f5deb3',
 white:                 '#ffffff',
 whitesmoke:            '#f5f5f5',
 yellow:                '#ffff00',
 yellowgreen:           '#9acd32'

};

/**

* These regular expressions are used to build up the patterns for matching
* viable CSS color strings: fragmenting the regexes in this way increases the
* legibility and comprehensibility of the code.
*
* Note that RGB values of .9 are not parsed by IE, but are supported here for
* color string consistency.
*/

var WHITESPACE = /\s*/; // Match zero or more whitespace characters. var INTEGER = /(\d{1,3})/; // Match integers: 79, 255, etc. var DECIMAL = /((?:\d+(?:\.\d+)?)|(?:\.\d+))/; // Match 129.6, 79, .9, etc. var PERCENT = new RegExp(DECIMAL.source + '%'); // Match 12.9%, 79%, .9%, etc.

/**

* Full color string patterns. The capture groups are necessary.
*/

var colorPatterns = {

 // Match colors in format #XXX, e.g. #416.
 HEX3: /^#([a-f0-9])([a-f0-9])([a-f0-9])$/i,
 // Match colors in format #XXXXXX, e.g. #b4d455.
 HEX6: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i,
 // Match colors in format rgb(R, G, B), e.g. rgb(255, 0, 128).
 RGB: new RegExp([
   '^rgb\\(',
   INTEGER.source,
   ',',
   INTEGER.source,
   ',',
   INTEGER.source,
   '\\)$'
 ].join(WHITESPACE.source), 'i'),
 // Match colors in format rgb(R%, G%, B%), e.g. rgb(100%, 0%, 28.9%).
 RGB_PERCENT: new RegExp([
   '^rgb\\(',
   PERCENT.source,
   ',',
   PERCENT.source,
   ',',
   PERCENT.source,
   '\\)$'
 ].join(WHITESPACE.source), 'i'),
 // Match colors in format rgb(R, G, B, A), e.g. rgb(255, 0, 128, 0.25).
 RGBA: new RegExp([
   '^rgba\\(',
   INTEGER.source,
   ',',
   INTEGER.source,
   ',',
   INTEGER.source,
   ',',
   DECIMAL.source,
   '\\)$'
 ].join(WHITESPACE.source), 'i'),
 // Match colors in format rgb(R%, G%, B%, A), e.g. rgb(100%, 0%, 28.9%, 0.5).
 RGBA_PERCENT: new RegExp([
   '^rgba\\(',
   PERCENT.source,
   ',',
   PERCENT.source,
   ',',
   PERCENT.source,
   ',',
   DECIMAL.source,
   '\\)$'
 ].join(WHITESPACE.source), 'i'),
 // Match colors in format hsla(H, S%, L%), e.g. hsl(100, 40%, 28.9%).
 HSL: new RegExp([
   '^hsl\\(',
   INTEGER.source,
   ',',
   PERCENT.source,
   ',',
   PERCENT.source,
   '\\)$'
 ].join(WHITESPACE.source), 'i'),
 // Match colors in format hsla(H, S%, L%, A), e.g. hsla(100, 40%, 28.9%, 0.5).
 HSLA: new RegExp([
   '^hsla\\(',
   INTEGER.source,
   ',',
   PERCENT.source,
   ',',
   PERCENT.source,
   ',',
   DECIMAL.source,
   '\\)$'
 ].join(WHITESPACE.source), 'i'),
 // Match colors in format hsb(H, S%, B%), e.g. hsb(100, 40%, 28.9%).
 HSB: new RegExp([
   '^hsb\\(',
   INTEGER.source,
   ',',
   PERCENT.source,
   ',',
   PERCENT.source,
   '\\)$'
 ].join(WHITESPACE.source), 'i'),
 // Match colors in format hsba(H, S%, B%, A), e.g. hsba(100, 40%, 28.9%, 0.5).
 HSBA: new RegExp([
   '^hsba\\(',
   INTEGER.source,
   ',',
   PERCENT.source,
   ',',
   PERCENT.source,
   ',',
   DECIMAL.source,
   '\\)$'
 ].join(WHITESPACE.source), 'i')

};

/**

* For a number of different inputs, returns a color formatted as [r, g, b, a]
* arrays, with each component normalized between 0 and 1.
*
* @param {Array-like} args An 'array-like' object that represents a list of
*                          arguments
* @return {Array}          a color formatted as [r, g, b, a]
*                          Example:
*                          input        ==> output
*                          g            ==> [g, g, g, 255]
*                          g,a          ==> [g, g, g, a]
*                          r, g, b      ==> [r, g, b, 255]
*                          r, g, b, a   ==> [r, g, b, a]
*                          [g]          ==> [g, g, g, 255]
*                          [g, a]       ==> [g, g, g, a]
*                          [r, g, b]    ==> [r, g, b, 255]
*                          [r, g, b, a] ==> [r, g, b, a]
* @example
*
* 
* // todo
* 
*
*
* @alt
* //todo
*
*/

p5.Color._parseInputs = function() {

 var numArgs = arguments.length;
 var mode = this._colorMode;
 var maxes = this._colorMaxes;
 var results = [];
 if (numArgs >= 3) {  // Argument is a list of component values.
   results[0] = arguments[0] / maxes[mode][0];
   results[1] = arguments[1] / maxes[mode][1];
   results[2] = arguments[2] / maxes[mode][2];
   // Alpha may be undefined, so default it to 100%.
   if (typeof arguments[3] === 'number') {
     results[3] = arguments[3] / maxes[mode][3];
   } else {
     results[3] = 1;
   }
   // Constrain components to the range [0,1].
   results = results.map(function(value) {
     return Math.max(Math.min(value, 1), 0);
   });
   // Convert to RGBA and return.
   if (mode === constants.HSL) {
     return color_conversion._hslaToRGBA(results);
   } else if (mode === constants.HSB) {
     return color_conversion._hsbaToRGBA(results);
   } else {
     return results;
   }
 } else if (numArgs === 1 && typeof arguments[0] === 'string') {
   var str = arguments[0].trim().toLowerCase();
   // Return if string is a named colour.
   if (namedColors[str]) {
     return p5.Color._parseInputs.apply(this, [namedColors[str]]);
   }
   // Try RGBA pattern matching.
   if (colorPatterns.HEX3.test(str)) {  // #rgb
     results = colorPatterns.HEX3.exec(str).slice(1).map(function(color) {
       return parseInt(color + color, 16) / 255;
     });
     results[3] = 1;
     return results;
   } else if (colorPatterns.HEX6.test(str)) {  // #rrggbb
     results = colorPatterns.HEX6.exec(str).slice(1).map(function(color) {
       return parseInt(color, 16) / 255;
     });
     results[3] = 1;
     return results;
   } else if (colorPatterns.RGB.test(str)) {  // rgb(R,G,B)
     results = colorPatterns.RGB.exec(str).slice(1).map(function(color) {
       return color / 255;
     });
     results[3] = 1;
     return results;
   } else if (colorPatterns.RGB_PERCENT.test(str)) {  // rgb(R%,G%,B%)
     results = colorPatterns.RGB_PERCENT.exec(str).slice(1)
       .map(function(color) {
         return parseFloat(color) / 100;
       });
     results[3] = 1;
     return results;
   } else if (colorPatterns.RGBA.test(str)) {  // rgba(R,G,B,A)
     results = colorPatterns.RGBA.exec(str).slice(1)
       .map(function(color, idx) {
         if (idx === 3) {
           return parseFloat(color);
         }
         return color / 255;
       });
     return results;
   } else if (colorPatterns.RGBA_PERCENT.test(str)) {  // rgba(R%,G%,B%,A%)
     results = colorPatterns.RGBA_PERCENT.exec(str).slice(1)
       .map(function(color, idx) {
         if (idx === 3) {
           return parseFloat(color);
         }
         return parseFloat(color) / 100;
       });
     return results;
   }
   // Try HSLA pattern matching.
   if (colorPatterns.HSL.test(str)) {  // hsl(H,S,L)
     results = colorPatterns.HSL.exec(str).slice(1)
       .map(function(color, idx) {
       if (idx === 0) {
         return parseInt(color, 10) / 360;
       }
       return parseInt(color, 10) / 100;
     });
     results[3] = 1;
   } else if (colorPatterns.HSLA.test(str)) {  // hsla(H,S,L,A)
     results = colorPatterns.HSLA.exec(str).slice(1)
       .map(function(color, idx) {
       if (idx === 0) {
         return parseInt(color, 10) / 360;
       }
       else if (idx === 3) {
         return parseFloat(color);
       }
       return parseInt(color, 10) / 100;
     });
   }
   if (results.length) {
     return color_conversion._hslaToRGBA(results);
   }
   // Try HSBA pattern matching.
   if (colorPatterns.HSB.test(str)) {  // hsb(H,S,B)
     results = colorPatterns.HSB.exec(str).slice(1)
       .map(function(color, idx) {
       if (idx === 0) {
         return parseInt(color, 10) / 360;
       }
       return parseInt(color, 10) / 100;
     });
     results[3] = 1;
   } else if (colorPatterns.HSBA.test(str)) {  // hsba(H,S,B,A)
     results = colorPatterns.HSBA.exec(str).slice(1)
       .map(function(color, idx) {
       if (idx === 0) {
         return parseInt(color, 10) / 360;
       }
       else if (idx === 3) {
         return parseFloat(color);
       }
       return parseInt(color, 10) / 100;
     });
   }
   if (results.length) {
     return color_conversion._hsbaToRGBA(results);
   }
   // Input did not match any CSS color pattern: default to white.
   results = [1, 1, 1, 1];
 } else if ((numArgs === 1 || numArgs === 2) &&
             typeof arguments[0] === 'number') {  // 'Grayscale' mode.
   /**
    * For HSB and HSL, interpret the gray level as a brightness/lightness
    * value (they are equivalent when chroma is zero). For RGB, normalize the
    * gray level according to the blue maximum.
    */
   results[0] = arguments[0] / maxes[mode][2];
   results[1] = arguments[0] / maxes[mode][2];
   results[2] = arguments[0] / maxes[mode][2];
   // Alpha may be undefined, so default it to 100%.
   if (typeof arguments[1] === 'number') {
     results[3] = arguments[1] / maxes[mode][3];
   } else {
     results[3] = 1;
   }
   // Constrain components to the range [0,1].
   results = results.map(function(value) {
     return Math.max(Math.min(value, 1), 0);
   });
 } else {
   throw new Error (arguments + 'is not a valid color representation.');
 }
 return results;

};

module.exports = p5.Color;

},{"../core/constants":36,"../core/core":37,"./color_conversion":29}],32:[function(_dereq_,module,exports){ /**

* @module Color
* @submodule Setting
* @for p5
* @requires core
* @requires constants
*/

'use strict';

var p5 = _dereq_('../core/core'); var constants = _dereq_('../core/constants'); _dereq_('./p5.Color');

/**

* The background() function sets the color used for the background of the
* p5.js canvas. The default background is light gray. This function is
* typically used within draw() to clear the display window at the beginning
* of each frame, but it can be used inside setup() to set the background on
* the first frame of animation or if the background need only be set once.
*
* @method background
* @param {p5.Color} color     any value created by the color() function
* @param {Number} [a]         opacity of the background relative to current
*                             color range (default is 0-100)
*
* @example
*
* 
* // Grayscale integer value
* background(51);
* 
*
*
*
* 
* // R, G & B integer values
* background(255, 204, 0);
* 
*
*
*
* 
* // H, S & B integer values
* colorMode(HSB);
* background(255, 204, 100);
* 
*
*
*
* 
* // Named SVG/CSS color string
* background('red');
* 
*
*
*
* 
* // three-digit hexadecimal RGB notation
* background('#fae');
* 
*
*
*
* 
* // six-digit hexadecimal RGB notation
* background('#222222');
* 
*
*
*
* 
* // integer RGB notation
* background('rgb(0,255,0)');
* 
*
*
*
* 
* // integer RGBA notation
* background('rgba(0,255,0, 0.25)');
* 
*
*
*
* 
* // percentage RGB notation
* background('rgb(100%,0%,10%)');
* 
*
*
*
* 
* // percentage RGBA notation
* background('rgba(100%,0%,100%,0.5)');
* 
*
*
*
* 
* // p5 Color object
* background(color(0, 0, 255));
* 
*
*
* @alt
* canvas with darkest charcoal grey background.
* canvas with yellow background.
* canvas with royal blue background.
* canvas with red background.
* canvas with pink background.
* canvas with black background.
* canvas with bright green background.
* canvas with soft green background.
* canvas with red background.
* canvas with light purple background.
* canvas with blue background.
*/

/**

* @method background
* @param {String} colorstring color string, possible formats include: integer
*                         rgb() or rgba(), percentage rgb() or rgba(),
*                         3-digit hex, 6-digit hex
* @param {Number} [a]
*/

/**

* @method background
* @param {Number} gray   specifies a value between white and black
* @param {Number} [a]
*/

/**

* @method background
* @param {Number} v1     red or hue value (depending on the current color
*                        mode)
* @param {Number} v2     green or saturation value (depending on the current
*                        color mode)
* @param {Number} v3     blue or brightness value (depending on the current
*                        color mode)
* @param  {Number} [a]
*/

/**

* @method background
* @param {p5.Image} image     image created with loadImage() or createImage(),
*                             to set as background
*                             (must be same size as the sketch window)
* @param  {Number}  [a]
*/

p5.prototype.background = function() {

 if (arguments[0] instanceof p5.Image) {
   this.image(arguments[0], 0, 0, this.width, this.height);
 } else {
   this._renderer.background.apply(this._renderer, arguments);
 }
 return this;

};

/**

* Clears the pixels within a buffer. This function only works on p5.Canvas
* objects created with the createCanvas() function; it won't work with the
* main display window. Unlike the main graphics context, pixels in
* additional graphics areas created with createGraphics() can be entirely
* or partially transparent. This function clears everything to make all of
* the pixels 100% transparent.
*
* @method clear
* @example
*
* 
* // Clear the screen on mouse press.
* function setup() {
*   createCanvas(100, 100);
* }
*
* function draw() {
*   ellipse(mouseX, mouseY, 20, 20);
* }
*
* function mousePressed() {
*   clear();
* }
* 
*
*
* @alt
* 20x20 white ellipses are continually drawn at mouse x and y coordinates.
*
*/

p5.prototype.clear = function() {

 this._renderer.clear();
 return this;

};

/**

* colorMode() changes the way p5.js interprets color data. By default, the
* parameters for fill(), stroke(), background(), and color() are defined by
* values between 0 and 255 using the RGB color model. This is equivalent to
* setting colorMode(RGB, 255). Setting colorMode(HSB) lets you use the HSB
* system instead. By default, this is colorMode(HSB, 360, 100, 100, 1). You
* can also use HSL.
* 

* Note: existing color objects remember the mode that they were created in, * so you can change modes as you like without affecting their appearance. * * @method colorMode * @param {Constant} mode either RGB or HSB, corresponding to * Red/Green/Blue and Hue/Saturation/Brightness * (or Lightness) * @param {Number} [max1] range for the red or hue depending on the * current color mode, or range for all values * @param {Number} [max2] range for the green or saturation depending * on the current color mode * @param {Number} [max3] range for the blue or brightness/lighntess * depending on the current color mode * @param {Number} [maxA] range for the alpha * @example
*
* 
* noStroke();
* colorMode(RGB, 100);
* for (i = 0; i < 100; i++) {
*   for (j = 0; j < 100; j++) {
*     stroke(i, j, 0);
*     point(i, j);
*   }
* }
* 
*
*
*
* 
* noStroke();
* colorMode(HSB, 100);
* for (i = 0; i < 100; i++) {
*   for (j = 0; j < 100; j++) {
*     stroke(i, j, 100);
*     point(i, j);
*   }
* }
* 
*
*
*
* 
* colorMode(RGB, 255);
* var c = color(127, 255, 0);
*
* colorMode(RGB, 1);
* var myColor = c._getRed();
* text(myColor, 10, 10, 80, 80);
* 
*
*
*
* 
* noFill();
* colorMode(RGB, 255, 255, 255, 1);
* background(255);
*
* strokeWeight(4);
* stroke(255, 0 , 10, 0.3);
* ellipse(40, 40, 50, 50);
* ellipse(50, 50, 40, 40);
* 
*
*
* @alt
*Green to red gradient from bottom L to top R. shading originates from top left.
*Rainbow gradient from left to right. Brightness increasing to white at top.
*unknown image.
*50x50 ellipse at middle L & 40x40 ellipse at center. Transluscent pink outlines.
*
*/

p5.prototype.colorMode = function() {

 if (arguments[0] === constants.RGB ||
     arguments[0] === constants.HSB ||
     arguments[0] === constants.HSL) {
   // Set color mode.
   this._renderer._colorMode = arguments[0];
   // Set color maxes.
   var maxes = this._renderer._colorMaxes[this._renderer._colorMode];
   if (arguments.length === 2) {
     maxes[0] = arguments[1];  // Red
     maxes[1] = arguments[1];  // Green
     maxes[2] = arguments[1];  // Blue
     maxes[3] = arguments[1];  // Alpha
   } else if (arguments.length === 4) {
     maxes[0] = arguments[1];  // Red
     maxes[1] = arguments[2];  // Green
     maxes[2] = arguments[3];  // Blue
   } else if (arguments.length === 5) {
     maxes[0] = arguments[1];  // Red
     maxes[1] = arguments[2];  // Green
     maxes[2] = arguments[3];  // Blue
     maxes[3] = arguments[4];  // Alpha
   }
 }
 return this;

};

/**

* Sets the color used to fill shapes. For example, if you run
* fill(204, 102, 0), all subsequent shapes will be filled with orange. This
* color is either specified in terms of the RGB or HSB color depending on
* the current colorMode(). (The default color space is RGB, with each value
* in the range from 0 to 255).
* 

* If a single string argument is provided, RGB, RGBA and Hex CSS color strings * and all named color strings are supported. A p5 Color object can also be * provided to set the fill color. * * @method fill * @param {Number|Array|String|p5.Color} v1 gray value, red or hue value * (depending on the current color * mode), or color Array, or CSS * color string * @param {Number} [v2] green or saturation value * (depending on the current * color mode) * @param {Number} [v3] blue or brightness value * (depending on the current * color mode) * @param {Number} [a] opacity of the background * * @example
*
* 
* // Grayscale integer value
* fill(51);
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // R, G & B integer values
* fill(255, 204, 0);
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // H, S & B integer values
* colorMode(HSB);
* fill(255, 204, 100);
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // Named SVG/CSS color string
* fill('red');
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // three-digit hexadecimal RGB notation
* fill('#fae');
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // six-digit hexadecimal RGB notation
* fill('#222222');
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // integer RGB notation
* fill('rgb(0,255,0)');
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // integer RGBA notation
* fill('rgba(0,255,0, 0.25)');
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // percentage RGB notation
* fill('rgb(100%,0%,10%)');
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // percentage RGBA notation
* fill('rgba(100%,0%,100%,0.5)');
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // p5 Color object
* fill(color(0, 0, 255));
* rect(20, 20, 60, 60);
* 
*
* @alt
* 60x60 dark charcoal grey rect with black outline in center of canvas.
* 60x60 yellow rect with black outline in center of canvas.
* 60x60 royal blue rect with black outline in center of canvas.
* 60x60 red rect with black outline in center of canvas.
* 60x60 pink rect with black outline in center of canvas.
* 60x60 black rect with black outline in center of canvas.
* 60x60 light green rect with black outline in center of canvas.
* 60x60 soft green rect with black outline in center of canvas.
* 60x60 red rect with black outline in center of canvas.
* 60x60 dark fushcia rect with black outline in center of canvas.
* 60x60 blue rect with black outline in center of canvas.
*/

p5.prototype.fill = function() {

 this._renderer._setProperty('_fillSet', true);
 this._renderer._setProperty('_doFill', true);
 this._renderer.fill.apply(this._renderer, arguments);
 return this;

};

/**

* Disables filling geometry. If both noStroke() and noFill() are called,
* nothing will be drawn to the screen.
*
* @method noFill
* @example
*
* 
* rect(15, 10, 55, 55);
* noFill();
* rect(20, 20, 60, 60);
* 
*
* @alt
* white rect top middle and noFill rect center. Both 60x60 with black outlines.
*/

p5.prototype.noFill = function() {

 this._renderer._setProperty('_doFill', false);
 return this;

};

/**

* Disables drawing the stroke (outline). If both noStroke() and noFill()
* are called, nothing will be drawn to the screen.
*
* @method noStroke
* @example
*
* 
* noStroke();
* rect(20, 20, 60, 60);
* 
*
*
*
* @alt
*60x60 white rect at center. no outline.
*
*/

p5.prototype.noStroke = function() {

 this._renderer._setProperty('_doStroke', false);
 return this;

};

/**

* Sets the color used to draw lines and borders around shapes. This color
* is either specified in terms of the RGB or HSB color depending on the
* current colorMode() (the default color space is RGB, with each value in
* the range from 0 to 255).
* 

* If a single string argument is provided, RGB, RGBA and Hex CSS color * strings and all named color strings are supported. A p5 Color object * can also be provided to set the stroke color. * * @method stroke * @param {Number|Array|String|p5.Color} v1 gray value, red or hue value * (depending on the current color * mode), or color Array, or CSS * color string * @param {Number} [v2] green or saturation value * (depending on the current * color mode) * @param {Number} [v3] blue or brightness value * (depending on the current * color mode) * @param {Number} [a] opacity of the background * * @example
*
* 
* // Grayscale integer value
* strokeWeight(4);
* stroke(51);
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // R, G & B integer values
* stroke(255, 204, 0);
* strokeWeight(4);
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // H, S & B integer values
* colorMode(HSB);
* strokeWeight(4);
* stroke(255, 204, 100);
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // Named SVG/CSS color string
* stroke('red');
* strokeWeight(4);
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // three-digit hexadecimal RGB notation
* stroke('#fae');
* strokeWeight(4);
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // six-digit hexadecimal RGB notation
* stroke('#222222');
* strokeWeight(4);
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // integer RGB notation
* stroke('rgb(0,255,0)');
* strokeWeight(4);
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // integer RGBA notation
* stroke('rgba(0,255,0,0.25)');
* strokeWeight(4);
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // percentage RGB notation
* stroke('rgb(100%,0%,10%)');
* strokeWeight(4);
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // percentage RGBA notation
* stroke('rgba(100%,0%,100%,0.5)');
* strokeWeight(4);
* rect(20, 20, 60, 60);
* 
*
*
*
* 
* // p5 Color object
* stroke(color(0, 0, 255));
* strokeWeight(4);
* rect(20, 20, 60, 60);
* 
*
*
* @alt
* 60x60 white rect at center. Dark charcoal grey outline.
* 60x60 white rect at center. Yellow outline.
* 60x60 white rect at center. Royal blue outline.
* 60x60 white rect at center. Red outline.
* 60x60 white rect at center. Pink outline.
* 60x60 white rect at center. Black outline.
* 60x60 white rect at center. Bright green outline.
* 60x60 white rect at center. Soft green outline.
* 60x60 white rect at center. Red outline.
* 60x60 white rect at center. Dark fushcia outline.
* 60x60 white rect at center. Blue outline.
*/

p5.prototype.stroke = function() {

 this._renderer._setProperty('_strokeSet', true);
 this._renderer._setProperty('_doStroke', true);
 this._renderer.stroke.apply(this._renderer, arguments);
 return this;

};

module.exports = p5;

},{"../core/constants":36,"../core/core":37,"./p5.Color":31}],33:[function(_dereq_,module,exports){ /**

* @module Shape
* @submodule 2D Primitives
* @for p5
* @requires core
* @requires constants
*/

'use strict';

var p5 = _dereq_('./core'); var constants = _dereq_('./constants'); var canvas = _dereq_('./canvas'); _dereq_('./error_helpers');

/**

* Draw an arc to the screen. If called with only a, b, c, d, start, and
* stop, the arc will be drawn as an open pie. If mode is provided, the arc
* will be drawn either open, as a chord, or as a pie as specified. The
* origin may be changed with the ellipseMode() function.

* Note that drawing a full circle (ex: 0 to TWO_PI) will appear blank * because 0 and TWO_PI are the same position on the unit circle. The * best way to handle this is by using the ellipse() function instead * to create a closed ellipse, and to use the arc() function * only to draw parts of an ellipse. * * @method arc * @param {Number} a x-coordinate of the arc's ellipse * @param {Number} b y-coordinate of the arc's ellipse * @param {Number} c width of the arc's ellipse by default * @param {Number} d height of the arc's ellipse by default * @param {Number} start angle to start the arc, specified in radians * @param {Number} stop angle to stop the arc, specified in radians * @param {Constant} [mode] optional parameter to determine the way of drawing * the arc * @return {Object} the p5 object * @example
*
* 
* arc(50, 55, 50, 50, 0, HALF_PI);
* noFill();
* arc(50, 55, 60, 60, HALF_PI, PI);
* arc(50, 55, 70, 70, PI, PI+QUARTER_PI);
* arc(50, 55, 80, 80, PI+QUARTER_PI, TWO_PI);
* 
*
*
*
* 
* arc(50, 50, 80, 80, 0, PI+QUARTER_PI, OPEN);
* 
*
*
*
* 
* arc(50, 50, 80, 80, 0, PI+QUARTER_PI, CHORD);
* 
*
*
*
* 
* arc(50, 50, 80, 80, 0, PI+QUARTER_PI, PIE);
* 
*
*
* @alt
*shattered outline of an ellipse with a quarter of a white circle bottom-right.
*white ellipse with black outline with top right missing.
*white ellipse with top right missing with black outline around shape.
*white ellipse with top right quarter missing with black outline around the shape.
*
*/

p5.prototype.arc = function(x, y, w, h, start, stop, mode) {

 var args = new Array(arguments.length);
 for (var i = 0; i < args.length; ++i) {
   args[i] = arguments[i];
 }
 if (!this._renderer._doStroke && !this._renderer._doFill) {
   return this;
 }
 if (this._angleMode === constants.DEGREES) {
   start = this.radians(start);
   stop = this.radians(stop);
 }
 // Make all angles positive...
 while (start < 0) {
   start += constants.TWO_PI;
 }
 while (stop < 0) {
   stop += constants.TWO_PI;
 }
 // ...and confine them to the interval [0,TWO_PI).
 start %= constants.TWO_PI;
 stop %= constants.TWO_PI;
 // account for full circle
 if (stop === start) {
   stop += constants.TWO_PI;
 }
 // Adjust angles to counter linear scaling.
 if (start <= constants.HALF_PI) {
   start = Math.atan(w / h * Math.tan(start));
 } else  if (start > constants.HALF_PI && start <= 3 * constants.HALF_PI) {
   start = Math.atan(w / h * Math.tan(start)) + constants.PI;
 } else {
   start = Math.atan(w / h * Math.tan(start)) + constants.TWO_PI;
 }
 if (stop <= constants.HALF_PI) {
   stop = Math.atan(w / h * Math.tan(stop));
 } else  if (stop > constants.HALF_PI && stop <= 3 * constants.HALF_PI) {
   stop = Math.atan(w / h * Math.tan(stop)) + constants.PI;
 } else {
   stop = Math.atan(w / h * Math.tan(stop)) + constants.TWO_PI;
 }
 // Exceed the interval if necessary in order to preserve the size and
 // orientation of the arc.
 if (start > stop) {
   stop += constants.TWO_PI;
 }
 // p5 supports negative width and heights for ellipses
 w = Math.abs(w);
 h = Math.abs(h);
 this._renderer.arc(x, y, w, h, start, stop, mode);
 return this;

};

/**

* Draws an ellipse (oval) to the screen. An ellipse with equal width and
* height is a circle. By default, the first two parameters set the location,
* and the third and fourth parameters set the shape's width and height. If
* no height is specified, the value of width is used for both the width and
* height. The origin may be changed with the ellipseMode() function.
*
* @method ellipse
* @param  {Number} x x-coordinate of the ellipse.
* @param  {Number} y y-coordinate of the ellipse.
* @param  {Number} w width of the ellipse.
* @param  {Number} [h] height of the ellipse.
* @return {p5}       the p5 object
* @example
*
* 
* ellipse(56, 46, 55, 55);
* 
*
*
* @alt
*white ellipse with black outline in middle-right of canvas that is 55x55.
*
*/

/**

* @method ellipse
* @param {Number} x
* @param {Number} y
* @param {Number} w
* @param {Number} [h]
* @return {p5}
*/

p5.prototype.ellipse = function() {

 var args = new Array(arguments.length);
 for (var i = 0; i < args.length; ++i) {
   args[i] = arguments[i];
 }
 // Duplicate 3rd argument if only 3 given.
 if (args.length === 3) {
   args.push(args[2]);
 }
 // p5 supports negative width and heights for rects
 if (args[2] < 0){args[2] = Math.abs(args[2]);}
 if (args[3] < 0){args[3] = Math.abs(args[3]);}
 if (!this._renderer._doStroke && !this._renderer._doFill) {
   return this;
 }
 var vals = canvas.modeAdjust(
   args[0],
   args[1],
   args[2],
   args[3],
   this._renderer._ellipseMode);
 args[0] = vals.x;
 args[1] = vals.y;
 args[2] = vals.w;
 args[3] = vals.h;
 this._renderer.ellipse(args);
 return this;

}; /**

* Draws a line (a direct path between two points) to the screen. The version
* of line() with four parameters draws the line in 2D. To color a line, use
* the stroke() function. A line cannot be filled, therefore the fill()
* function will not affect the color of a line. 2D lines are drawn with a
* width of one pixel by default, but this can be changed with the
* strokeWeight() function.
*
* @method line
* @param  {Number} x1 the x-coordinate of the first point
* @param  {Number} y1 the y-coordinate of the first point
* @param  {Number} x2 the x-coordinate of the second point
* @param  {Number} y2 the y-coordinate of the second point
* @return {p5}        the p5 object
* @example
*
* 
* line(30, 20, 85, 75);
* 
*
*
*
* 
* line(30, 20, 85, 20);
* stroke(126);
* line(85, 20, 85, 75);
* stroke(255);
* line(85, 75, 30, 75);
* 
*
*
* @alt
*line 78 pixels long running from mid-top to bottom-right of canvas.
*3 lines of various stroke sizes. Form top, bottom and right sides of a square.
*
*/

////commented out original // p5.prototype.line = function(x1, y1, x2, y2) { // if (!this._renderer._doStroke) { // return this; // } // if(this._renderer.isP3D){ // } else { // this._renderer.line(x1, y1, x2, y2); // } // }; p5.prototype.line = function() {

 if (!this._renderer._doStroke) {
   return this;
 }
 var args = new Array(arguments.length);
 for (var i = 0; i < args.length; ++i) {
   args[i] = arguments[i];
 }
 //check whether we should draw a 3d line or 2d
 if(this._renderer.isP3D){
   this._renderer.line(
     args[0],
     args[1],
     args[2],
     args[3],
     args[4],
     args[5]);
 } else {
   this._renderer.line(
     args[0],
     args[1],
     args[2],
     args[3]);
 }
 return this;

};

/**

* Draws a point, a coordinate in space at the dimension of one pixel.
* The first parameter is the horizontal value for the point, the second
* value is the vertical value for the point. The color of the point is
* determined by the current stroke.
*
* @method point
* @param  {Number} x the x-coordinate
* @param  {Number} y the y-coordinate
* @return {p5}       the p5 object
* @example
*
* 
* point(30, 20);
* point(85, 20);
* point(85, 75);
* point(30, 75);
* 
*
*
* @alt
*4 points centered in the middle-right of the canvas.
*
*/

p5.prototype.point = function() {

 if (!this._renderer._doStroke) {
   return this;
 }
 var args = new Array(arguments.length);
 for (var i = 0; i < args.length; ++i) {
   args[i] = arguments[i];
 }
 //check whether we should draw a 3d line or 2d
 if(this._renderer.isP3D){
   this._renderer.point(
     args[0],
     args[1],
     args[2]
     );
 } else {
   this._renderer.point(
     args[0],
     args[1]
   );
 }
 return this;

};


/**

* Draw a quad. A quad is a quadrilateral, a four sided polygon. It is
* similar to a rectangle, but the angles between its edges are not
* constrained to ninety degrees. The first pair of parameters (x1,y1)
* sets the first vertex and the subsequent pairs should proceed
* clockwise or counter-clockwise around the defined shape.
*
* @method quad
* @param {Number} x1 the x-coordinate of the first point
* @param {Number} y1 the y-coordinate of the first point
* @param {Number} x2 the x-coordinate of the second point
* @param {Number} y2 the y-coordinate of the second point
* @param {Number} x3 the x-coordinate of the third point
* @param {Number} y3 the y-coordinate of the third point
* @param {Number} x4 the x-coordinate of the fourth point
* @param {Number} y4 the y-coordinate of the fourth point
* @return {p5}     the p5 object
* @example
*
* 
* quad(38, 31, 86, 20, 69, 63, 30, 76);
* 
*
*
* @alt
*irregular white quadrilateral shape with black outline mid-right of canvas.
*
*/

/**

* @method quad
* @param {Number} x1
* @param {Number} y1
* @param {Number} x2
* @param {Number} y2
* @param {Number} x3
* @param {Number} y3
* @param {Number} x4
* @param {Number} y4
* @return {p5} the p5 object
*/

p5.prototype.quad = function() {

 if (!this._renderer._doStroke && !this._renderer._doFill) {
   return this;
 }
 var args = new Array(arguments.length);
 for (var i = 0; i < args.length; ++i) {
   args[i] = arguments[i];
 }
 if(this._renderer.isP3D){
   this._renderer.quad(
     args[0],
     args[1],
     args[2],
     args[3],
     args[4],
     args[5],
     args[6],
     args[7],
     args[8],
     args[9],
     args[10],
     args[11]
     );
 } else {
   this._renderer.quad(
    args[0],
    args[1],
    args[2],
    args[3],
    args[4],
    args[5],
    args[6],
   args[7]
   );
 }
 return this;

};

/**

  • Draws a rectangle to the screen. A rectangle is a four-sided shape with
  • every angle at ninety degrees. By default, the first two parameters set
  • the location of the upper-left corner, the third sets the width, and the
  • fourth sets the height. The way these parameters are interpreted, however,
  • may be changed with the rectMode() function.


  • The fifth, sixth, seventh and eighth parameters, if specified,
  • determine corner radius for the top-right, top-left, lower-right and
  • lower-left corners, respectively. An omitted corner radius parameter is set
  • to the value of the previously specified radius value in the parameter list.
  • @method rect
  • @param {Number} x x-coordinate of the rectangle.
  • @param {Number} y y-coordinate of the rectangle.
  • @param {Number} w width of the rectangle.
  • @param {Number} h height of the rectangle.
  • @param {Number} [tl] optional radius of top-left corner.
  • @param {Number} [tr] optional radius of top-right corner.
  • @param {Number} [br] optional radius of bottom-right corner.
  • @param {Number} [bl] optional radius of bottom-left corner.
  • @return {p5} the p5 object.
  • @example
  • // Draw a rectangle at location (30, 20) with a width and height of 55.
  • rect(30, 20, 55, 55);
  • // Draw a rectangle with rounded corners, each having a radius of 20.
  • rect(30, 20, 55, 55, 20);
  • // Draw a rectangle with rounded corners having the following radii:
  • // top-left = 20, top-right = 15, bottom-right = 10, bottom-left = 5.
  • rect(30, 20, 55, 55, 20, 15, 10, 5);
  • @alt
  • 55x55 white rect with black outline in mid-right of canvas.
  • 55x55 white rect with black outline and rounded edges in mid-right of canvas.
  • 55x55 white rect with black outline and rounded edges of different radii.
  • /
  • /**

    p5.prototype.rect = function () {

     var args = new Array(arguments.length);
     for (var i = 0; i < args.length; ++i) {
       args[i] = arguments[i];
     }
     if (!this._renderer._doStroke && !this._renderer._doFill) {
       return;
     }
     var vals = canvas.modeAdjust(
       args[0],
       args[1],
       args[2],
       args[3],
       this._renderer._rectMode);
     args[0] = vals.x;
     args[1] = vals.y;
     args[2] = vals.w;
     args[3] = vals.h;
     this._renderer.rect(args);
     return this;
    

    };

    /**