/*!
 * Copyright (c) 2009 Simo Kinnunen.
 * Licensed under the MIT license.
 *
 * @version ${Version}
 */


var Cufon = (function() {

	var api = function() {
		return api.replace.apply(null, arguments);
	};

	var DOM = api.DOM = {

		ready: (function() {

			var complete = false, readyStatus = { loaded: 1, complete: 1 };

			var queue = [], perform = function() {
				if (complete) return;
				complete = true;
				for (var fn; fn = queue.shift(); fn());
			};

			// Gecko, Opera, WebKit r26101+

			if (document.addEventListener) {
				document.addEventListener('DOMContentLoaded', perform, false);
				window.addEventListener('pageshow', perform, false); // For cached Gecko pages
			}

			// Old WebKit, Internet Explorer

			if (!window.opera && document.readyState) (function() {
				readyStatus[document.readyState] ? perform() : setTimeout(arguments.callee, 10);
			})();

			// Internet Explorer

			if (document.readyState && document.createStyleSheet) (function() {
				try {
					document.body.doScroll('left');
					perform();
				}
				catch (e) {
					setTimeout(arguments.callee, 1);
				}
			})();

			addEvent(window, 'load', perform); // Fallback

			return function(listener) {
				if (!arguments.length) perform();
				else complete ? listener() : queue.push(listener);
			};

		})(),

		root: function() {
			return document.documentElement || document.body;
		}

	};

	var CSS = api.CSS = {

		Size: function(value, base) {

			this.value = parseFloat(value);
			this.unit = String(value).match(/[a-z%]*$/)[0] || 'px';

			this.convert = function(value) {
				return value / base * this.value;
			};

			this.convertFrom = function(value) {
				return value / this.value * base;
			};

			this.toString = function() {
				return this.value + this.unit;
			};

		},

		addClass: function(el, className) {
			var current = el.className;
			el.className = current + (current && ' ') + className;
			return el;
		},

		color: cached(function(value) {
			var parsed = {};
			parsed.color = value.replace(/^rgba\((.*?),\s*([\d.]+)\)/, function($0, $1, $2) {
				parsed.opacity = parseFloat($2);
				return 'rgb(' + $1 + ')';
			});
			return parsed;
		}),

		// has no direct CSS equivalent.
		// @see http://msdn.microsoft.com/en-us/library/system.windows.fontstretches.aspx
		fontStretch: cached(function(value) {
			if (typeof value == 'number') return value;
			if (/%$/.test(value)) return parseFloat(value) / 100;
			return {
				'ultra-condensed': 0.5,
				'extra-condensed': 0.625,
				condensed: 0.75,
				'semi-condensed': 0.875,
				'semi-expanded': 1.125,
				expanded: 1.25,
				'extra-expanded': 1.5,
				'ultra-expanded': 2
			}[value] || 1;
		}),

		getStyle: function(el) {
			var view = document.defaultView;
			if (view && view.getComputedStyle) return new Style(view.getComputedStyle(el, null));
			if (el.currentStyle) return new Style(el.currentStyle);
			return new Style(el.style);
		},

		gradient: cached(function(value) {
			var gradient = {
				id: value,
				type: value.match(/^-([a-z]+)-gradient\(/)[1],
				stops: []
			}, colors = value.substr(value.indexOf('(')).match(/([\d.]+=)?(#[a-f0-9]+|[a-z]+\(.*?\)|[a-z]+)/ig);
			for (var i = 0, l = colors.length, stop; i < l; ++i) {
				stop = colors[i].split('=', 2).reverse();
				gradient.stops.push([ stop[1] || i / (l - 1), stop[0] ]);
			}
			return gradient;
		}),

		hasClass: function(el, className) {
			return RegExp('(?:^|\\s)' + className +  '(?=\\s|$)').test(el.className);
		},

		quotedList: cached(function(value) {
			// doesn't work properly with empty quoted strings (""), but
			// it's not worth the extra code.
			var list = [], re = /\s*((["'])([\s\S]*?[^\\])\2|[^,]+)\s*/g, match;
			while (match = re.exec(value)) list.push(match[3] || match[1]);
			return list;
		}),

		recognizesMedia: cached(function(media) {
			var el = document.createElement('style'), sheet, container, supported;
			el.type = 'text/css';
			el.media = media;
			try { // this is cached anyway
				el.appendChild(document.createTextNode('/**/'));
			} catch (e) {}
			container = elementsByTagName('head')[0];
			container.insertBefore(el, container.firstChild);
			sheet = (el.sheet || el.styleSheet);
			supported = sheet && !sheet.disabled;
			container.removeChild(el);
			return supported;
		}),

		removeClass: function(el, className) {
			var re = RegExp('(?:^|\\s+)' + className +  '(?=\\s|$)', 'g');
			el.className = el.className.replace(re, '');
			return el;
		},

		supports: function(property, value) {
			var checker = document.createElement('span').style;
			if (checker[property] === undefined) return false;
			checker[property] = value;
			return checker[property] === value;
		},

		textAlign: function(word, style, position, wordCount) {
			if (style.get('textAlign') == 'right') {
				if (position > 0) word = ' ' + word;
			}
			else if (position < wordCount - 1) word += ' ';
			return word;
		},

		textDecoration: function(el, style) {
			if (!style) style = this.getStyle(el);
			var types = {
				underline: null,
				overline: null,
				'line-through': null
			};
			for (var search = el; search.parentNode && search.parentNode.nodeType == 1; ) {
				var foundAll = true;
				for (var type in types) {
					if (!hasOwnProperty(types, type) || types[type]) continue;
					if (style.get('textDecoration').indexOf(type) != -1) types[type] = style.get('color');
					foundAll = false;
				}
				if (foundAll) break; // this is rather unlikely to happen
				style = this.getStyle(search = search.parentNode);
			}
			return types;
		},

		textShadow: cached(function(value) {
			if (value == 'none') return null;
			var shadows = [], currentShadow = {}, result, offCount = 0;
			var re = /(#[a-f0-9]+|[a-z]+\(.*?\)|[a-z]+)|(-?[\d.]+[a-z%]*)|,/ig;
			while (result = re.exec(value)) {
				if (result[0] == ',') {
					shadows.push(currentShadow);
					currentShadow = {};
					offCount = 0;
				}
				else if (result[1]) {
					currentShadow.color = result[1];
				}
				else {
					currentShadow[[ 'offX', 'offY', 'blur' ][offCount++]] = result[2];
				}
			}
			shadows.push(currentShadow);
			return shadows;
		}),

		textTransform: (function() {
			var map = {
				uppercase: function(s) {
					return s.toUpperCase();
				},
				lowercase: function(s) {
					return s.toLowerCase();
				},
				capitalize: function(s) {
					return s.replace(/\b./g, function($0) {
						return $0.toUpperCase();
					});
				}
			};
			return function(text, style) {
				var transform = map[style.get('textTransform')];
				return transform ? transform(text) : text;
			};
		})(),

		whiteSpace: (function() {
			var ignore = {
				inline: 1,
				'inline-block': 1,
				'run-in': 1
			};
			return function(text, style, node) {
				if (ignore[style.get('display')]) return text;
				if (!node.previousSibling) text = text.replace(/^\s+/, '');
				if (!node.nextSibling) text = text.replace(/\s+$/, '');
				return text;
			};
		})()

	};

	CSS.ready = (function() {

		// don't do anything in Safari 2 (it doesn't recognize any media type)
		var complete = !CSS.recognizesMedia('all'), hasLayout = false;

		var queue = [], perform = function() {
			complete = true;
			for (var fn; fn = queue.shift(); fn());
		};

		var links = elementsByTagName('link'), styles = elementsByTagName('style');

		function isContainerReady(el) {
			return el.disabled || isSheetReady(el.sheet, el.media || 'screen');
		}

		function isSheetReady(sheet, media) {
			// in Opera sheet.disabled is true when it's still loading,
			// even though link.disabled is false. they stay in sync if
			// set manually.
			if (!CSS.recognizesMedia(media || 'all')) return true;
			if (!sheet || sheet.disabled) return false;
			try {
				var rules = sheet.cssRules, rule;
				if (rules) {
					// needed for Safari 3 and Chrome 1.0.
					// in standards-conforming browsers cssRules contains @-rules.
					// Chrome 1.0 weirdness: rules[<number larger than .length - 1>]
					// returns the last rule, so a for loop is the only option.
					search: for (var i = 0, l = rules.length; rule = rules[i], i < l; ++i) {
						switch (rule.type) {
							case 2: // @charset
								break;
							case 3: // @import
								if (!isSheetReady(rule.styleSheet, rule.media.mediaText)) return false;
								break;
							default:
								// only @charset can precede @import
								break search;
						}
					}
				}
			}
			catch (e) {} // probably a style sheet from another domain
			return true;
		}

		function allStylesLoaded() {
			// Internet Explorer's style sheet model, there's no need to do anything
			if (document.createStyleSheet) return true;
			// standards-compliant browsers
			var el, i;
			for (i = 0; el = links[i]; ++i) {
				if (el.rel.toLowerCase() == 'stylesheet' && !isContainerReady(el)) return false;
			}
			for (i = 0; el = styles[i]; ++i) {
				if (!isContainerReady(el)) return false;
			}
			return true;
		}

		DOM.ready(function() {
			// getComputedStyle returns null in Gecko if used in an iframe with display: none
			if (!hasLayout) hasLayout = CSS.getStyle(document.body).isUsable();
			if (complete || (hasLayout && allStylesLoaded())) perform();
			else setTimeout(arguments.callee, 10);
		});

		return function(listener) {
			if (complete) listener();
			else queue.push(listener);
		};

	})();

	function Font(data) {

		var face = this.face = data.face;
		this.glyphs = data.glyphs;
		this.w = data.w;
		this.baseSize = parseInt(face['units-per-em'], 10);

		this.family = face['font-family'].toLowerCase();
		this.weight = face['font-weight'];
		this.style = face['font-style'] || 'normal';

		this.viewBox = (function () {
			var parts = face.bbox.split(/\s+/);
			var box = {
				minX: parseInt(parts[0], 10),
				minY: parseInt(parts[1], 10),
				maxX: parseInt(parts[2], 10),
				maxY: parseInt(parts[3], 10)
			};
			box.width = box.maxX - box.minX;
			box.height = box.maxY - box.minY;
			box.toString = function() {
				return [ this.minX, this.minY, this.width, this.height ].join(' ');
			};
			return box;
		})();

		this.ascent = -parseInt(face.ascent, 10);
		this.descent = -parseInt(face.descent, 10);

		this.height = -this.ascent + this.descent;

	}

	function FontFamily() {

		var styles = {}, mapping = {
			oblique: 'italic',
			italic: 'oblique'
		};

		this.add = function(font) {
			(styles[font.style] || (styles[font.style] = {}))[font.weight] = font;
		};

		this.get = function(style, weight) {
			var weights = styles[style] || styles[mapping[style]]
				|| styles.normal || styles.italic || styles.oblique;
			if (!weights) return null;
			// we don't have to worry about "bolder" and "lighter"
			// because IE's currentStyle returns a numeric value for it,
			// and other browsers use the computed value anyway
			weight = {
				normal: 400,
				bold: 700
			}[weight] || parseInt(weight, 10);
			if (weights[weight]) return weights[weight];
			// http://www.w3.org/TR/CSS21/fonts.html#propdef-font-weight
			// Gecko uses x99/x01 for lighter/bolder
			var up = {
				1: 1,
				99: 0
			}[weight % 100], alts = [], min, max;
			if (up === undefined) up = weight > 400;
			if (weight == 500) weight = 400;
			for (var alt in weights) {
				if (!hasOwnProperty(weights, alt)) continue;
				alt = parseInt(alt, 10);
				if (!min || alt < min) min = alt;
				if (!max || alt > max) max = alt;
				alts.push(alt);
			}
			if (weight < min) weight = min;
			if (weight > max) weight = max;
			alts.sort(function(a, b) {
				return (up
					? (a > weight && b > weight) ? a < b : a > b
					: (a < weight && b < weight) ? a > b : a < b) ? -1 : 1;
			});
			return weights[alts[0]];
		};

	}

	function HoverHandler() {

		function contains(node, anotherNode) {
			if (node.contains) return node.contains(anotherNode);
			return node.compareDocumentPosition(anotherNode) & 16;
		}

		function onOverOut(e) {
			var related = e.relatedTarget;
			if (!related || contains(this, related)) return;
			trigger(this);
		}

		function onEnterLeave(e) {
			trigger(this);
		}

		function trigger(el) {
			// A timeout is needed so that the event can actually "happen"
			// before replace is triggered. This ensures that styles are up
			// to date.
			setTimeout(function() {
				api.replace(el, sharedStorage.get(el).options, true);
			}, 10);
		}

		this.attach = function(el) {
			if (el.onmouseenter === undefined) {
				addEvent(el, 'mouseover', onOverOut);
				addEvent(el, 'mouseout', onOverOut);
			}
			else {
				addEvent(el, 'mouseenter', onEnterLeave);
				addEvent(el, 'mouseleave', onEnterLeave);
			}
		};

	}

	function ReplaceHistory() {

		var list = [], map = {};

		function filter(keys) {
			var values = [], key;
			for (var i = 0; key = keys[i]; ++i) values[i] = list[map[key]];
			return values;
		}

		this.add = function(key, args) {
			map[key] = list.push(args) - 1;
		};

		this.repeat = function() {
			var snapshot = arguments.length ? filter(arguments) : list, args;
			for (var i = 0; args = snapshot[i++];) api.replace(args[0], args[1], true);
		};

	}

	function Storage() {

		var map = {}, at = 0;

		function identify(el) {
			return el.cufid || (el.cufid = ++at);
		}

		this.get = function(el) {
			var id = identify(el);
			return map[id] || (map[id] = {});
		};

	}

	function Style(style) {

		var custom = {}, sizes = {};

		this.extend = function(styles) {
			for (var property in styles) {
				if (hasOwnProperty(styles, property)) custom[property] = styles[property];
			}
			return this;
		};

		this.get = function(property) {
			return custom[property] != undefined ? custom[property] : style[property];
		};

		this.getSize = function(property, base) {
			return sizes[property] || (sizes[property] = new CSS.Size(this.get(property), base));
		};

		this.isUsable = function() {
			return !!style;
		};

	}

	function addEvent(el, type, listener) {
		if (el.addEventListener) {
			el.addEventListener(type, listener, false);
		}
		else if (el.attachEvent) {
			el.attachEvent('on' + type, function() {
				return listener.call(el, window.event);
			});
		}
	}

	function attach(el, options) {
		var storage = sharedStorage.get(el);
		if (storage.options) return el;
		if (options.hover && options.hoverables[el.nodeName.toLowerCase()]) {
			hoverHandler.attach(el);
		}
		storage.options = options;
		return el;
	}

	function cached(fun) {
		var cache = {};
		return function(key) {
			if (!hasOwnProperty(cache, key)) cache[key] = fun.apply(null, arguments);
			return cache[key];
		};
	}

	function getFont(el, style) {
		var families = CSS.quotedList(style.get('fontFamily').toLowerCase()), family;
		for (var i = 0; family = families[i]; ++i) {
			if (fonts[family]) return fonts[family].get(style.get('fontStyle'), style.get('fontWeight'));
		}
		return null;
	}

	function elementsByTagName(query) {
		return document.getElementsByTagName(query);
	}

	function hasOwnProperty(obj, property) {
		return obj.hasOwnProperty(property);
	}

	function merge() {
		var merged = {}, args, key;
		for (var i = 0, l = arguments.length; args = arguments[i], i < l; ++i) {
			for (key in args) {
				if (hasOwnProperty(args, key)) merged[key] = args[key];
			}
		}
		return merged;
	}

	function process(font, text, style, options, node, el) {
		var fragment = document.createDocumentFragment(), processed;
		if (text === '') return fragment;
		var separate = options.separate;
		var parts = text.split(separators[separate]), needsAligning = (separate == 'words');
		if (needsAligning && HAS_BROKEN_REGEXP) {
			// @todo figure out a better way to do this
			if (/^\s/.test(text)) parts.unshift('');
			if (/\s$/.test(text)) parts.push('');
		}
		for (var i = 0, l = parts.length; i < l; ++i) {
			processed = engines[options.engine](font,
				needsAligning ? CSS.textAlign(parts[i], style, i, l) : parts[i],
				style, options, node, el, i < l - 1);
			if (processed) fragment.appendChild(processed);
		}
		return fragment;
	}

	function replaceElement(el, options) {
		var style = CSS.getStyle(attach(el, options)).extend(options);
		var font = getFont(el, style), node, type, next, anchor, text;
		for (node = el.firstChild; node; node = next) {
			type = node.nodeType;
			next = node.nextSibling;
			if (type == 3) {
				// Node.normalize() is broken in IE 6, 7, 8
				if (anchor) {
					anchor.appendData(node.data);
					el.removeChild(node);
				}
				else anchor = node;
				if (next) continue;
			}
			if (anchor) {
				el.replaceChild(process(font,
					CSS.whiteSpace(anchor.data, style, anchor),
					style, options, node, el), anchor);
				anchor = null;
			}
			if (type == 1 && node.firstChild) {
				if (CSS.hasClass(node, 'cufon')) {
					engines[options.engine](font, null, style, options, node, el);
				}
				else arguments.callee(node, options);
			}
		}
	}

	var HAS_BROKEN_REGEXP = ' '.split(/\s+/).length == 0;

	var sharedStorage = new Storage();
	var hoverHandler = new HoverHandler();
	var replaceHistory = new ReplaceHistory();
	var initialized = false;

	var engines = {}, fonts = {}, defaultOptions = {
		enableTextDecoration: false,
		engine: null,
		//fontScale: 1,
		//fontScaling: false,
		forceHitArea: false,
		hover: false,
		hoverables: {
			a: true
		},
		printable: true,
		//rotation: 0,
		//selectable: false,
		selector: (
				window.Sizzle
			||	(window.jQuery && function(query) { return jQuery(query); }) // avoid noConflict issues
			||	(window.dojo && dojo.query)
			||	(window.Ext && Ext.query)
			||	(window.$$ && function(query) { return $$(query); })
			||	(window.$ && function(query) { return $(query); })
			||	(document.querySelectorAll && function(query) { return document.querySelectorAll(query); })
			||	elementsByTagName
		),
		separate: 'words', // 'none' and 'characters' are also accepted
		textShadow: 'none'
	};

	var separators = {
		words: /[^\S\u00a0]+/,
		characters: '',
		none: /^/
	};

	api.now = function() {
		DOM.ready();
		return api;
	};

	api.refresh = function() {
		replaceHistory.repeat.apply(replaceHistory, arguments);
		return api;
	};

	api.registerEngine = function(id, engine) {
		if (!engine) return api;
		engines[id] = engine;
		return api.set('engine', id);
	};

	api.registerFont = function(data) {
		var font = new Font(data), family = font.family;
		if (!fonts[family]) fonts[family] = new FontFamily();
		fonts[family].add(font);
		return api.set('fontFamily', '"' + family + '"');
	};

	api.replace = function(elements, options, ignoreHistory) {
		options = merge(defaultOptions, options);
		if (!options.engine) return api; // there's no browser support so we'll just stop here
		if (!initialized) {
			CSS.addClass(DOM.root(), 'cufon-active cufon-loading');
			CSS.ready(function() {
				// fires before any replace() calls, but it doesn't really matter
				CSS.addClass(CSS.removeClass(DOM.root(), 'cufon-loading'), 'cufon-ready');
			});
			initialized = true;
		}
		if (options.hover) options.forceHitArea = true;
		if (typeof options.textShadow == 'string')
			options.textShadow = CSS.textShadow(options.textShadow);
		if (typeof options.color == 'string' && /^-/.test(options.color))
			options.textGradient = CSS.gradient(options.color);
		if (!ignoreHistory) replaceHistory.add(elements, arguments);
		if (elements.nodeType || typeof elements == 'string') elements = [ elements ];
		CSS.ready(function() {
			for (var i = 0, l = elements.length; i < l; ++i) {
				var el = elements[i];
				if (typeof el == 'string') api.replace(options.selector(el), options, true);
				else replaceElement(el, options);
			}
		});
		return api;
	};

	api.set = function(option, value) {
		defaultOptions[option] = value;
		return api;
	};

	return api;

})();

Cufon.registerEngine('canvas', (function() {

	// Safari 2 doesn't support .apply() on native methods

	var check = document.createElement('canvas');
	if (!check || !check.getContext || !check.getContext.apply) return;
	check = null;

	var HAS_INLINE_BLOCK = Cufon.CSS.supports('display', 'inline-block');

	// Firefox 2 w/ non-strict doctype (almost standards mode)
	var HAS_BROKEN_LINEHEIGHT = !HAS_INLINE_BLOCK && (document.compatMode == 'BackCompat' || /frameset|transitional/i.test(document.doctype.publicId));

	var styleSheet = document.createElement('style');
	styleSheet.type = 'text/css';
	styleSheet.appendChild(document.createTextNode((
		'.cufon-canvas{text-indent:0;}' +
		'@media screen,projection{' +
			'.cufon-canvas{display:inline;display:inline-block;position:relative;vertical-align:middle;' +
			(HAS_BROKEN_LINEHEIGHT
				? ''
				: 'font-size:1px;line-height:1px;') +
			'}.cufon-canvas .cufon-alt{display:-moz-inline-box;display:inline-block;width:0;height:0;overflow:hidden;text-indent:-10000in;}' +
			(HAS_INLINE_BLOCK
				? '.cufon-canvas canvas{position:relative;}'
				: '.cufon-canvas canvas{position:absolute;}') +
		'}' +
		'@media print{' +
			'.cufon-canvas{padding:0;}' +
			'.cufon-canvas canvas{display:none;}' +
			'.cufon-canvas .cufon-alt{display:inline;}' +
		'}'
	).replace(/;/g, '!important;')));
	document.getElementsByTagName('head')[0].appendChild(styleSheet);

	function generateFromVML(path, context) {
		var atX = 0, atY = 0;
		var code = [], re = /([mrvxe])([^a-z]*)/g, match;
		generate: for (var i = 0; match = re.exec(path); ++i) {
			var c = match[2].split(',');
			switch (match[1]) {
				case 'v':
					code[i] = { m: 'bezierCurveTo', a: [ atX + ~~c[0], atY + ~~c[1], atX + ~~c[2], atY + ~~c[3], atX += ~~c[4], atY += ~~c[5] ] };
					break;
				case 'r':
					code[i] = { m: 'lineTo', a: [ atX += ~~c[0], atY += ~~c[1] ] };
					break;
				case 'm':
					code[i] = { m: 'moveTo', a: [ atX = ~~c[0], atY = ~~c[1] ] };
					break;
				case 'x':
					code[i] = { m: 'closePath' };
					break;
				case 'e':
					break generate;
			}
			context[code[i].m].apply(context, code[i].a);
		}
		return code;
	}

	function interpret(code, context) {
		for (var i = 0, l = code.length; i < l; ++i) {
			var line = code[i];
			context[line.m].apply(context, line.a);
		}
	}

	return function(font, text, style, options, node, el) {

		var redraw = (text === null);

		if (redraw) text = node.alt;

		var viewBox = font.viewBox;

		var size = style.getSize('fontSize', font.baseSize);

		var letterSpacing = style.get('letterSpacing');
		letterSpacing = (letterSpacing == 'normal') ? 0 : size.convertFrom(parseInt(letterSpacing, 10));

		var expandTop = 0, expandRight = 0, expandBottom = 0, expandLeft = 0;
		var shadows = options.textShadow, shadowOffsets = [];
		if (shadows) {
			for (var i = shadows.length; i--;) {
				var shadow = shadows[i];
				var x = size.convertFrom(parseFloat(shadow.offX));
				var y = size.convertFrom(parseFloat(shadow.offY));
				shadowOffsets[i] = [ x, y ];
				if (y < expandTop) expandTop = y;
				if (x > expandRight) expandRight = x;
				if (y > expandBottom) expandBottom = y;
				if (x < expandLeft) expandLeft = x;
			}
		}

		var chars = Cufon.CSS.textTransform(text, style).split(''), chr;

		var glyphs = font.glyphs, glyph, kerning, k;
		var width = 0, advance, jumps = [];

		for (var i = 0, j = 0, l = chars.length; i < l; ++i) {
			glyph = glyphs[chr = chars[i]] || font.missingGlyph;
			if (!glyph) continue;
			if (kerning) {
				width -= k = kerning[chr] || 0;
				jumps[j - 1] -= k;
			}
			width += advance = jumps[j++] = ~~(glyph.w || font.w) + letterSpacing;
			kerning = glyph.k;
		}

		if (advance === undefined) return null; // there's nothing to render

		expandRight += viewBox.width - advance;
		expandLeft += viewBox.minX;

		var wrapper, canvas;

		if (redraw) {
			wrapper = node;
			canvas = node.firstChild;
		}
		else {
			wrapper = document.createElement('span');
			wrapper.className = 'cufon cufon-canvas';
			wrapper.alt = text;

			canvas = document.createElement('canvas');
			wrapper.appendChild(canvas);

			if (options.printable) {
				var print = document.createElement('span');
				print.className = 'cufon-alt';
				print.appendChild(document.createTextNode(text));
				wrapper.appendChild(print);
			}
		}

		var wStyle = wrapper.style;
		var cStyle = canvas.style;

		var height = size.convert(viewBox.height);
		var roundedHeight = Math.ceil(height);
		var roundingFactor = roundedHeight / height;
		var stretchFactor = roundingFactor * Cufon.CSS.fontStretch(style.get('fontStretch'));
		var stretchedWidth = width * stretchFactor;

		var canvasWidth = Math.ceil(size.convert(stretchedWidth + expandRight - expandLeft));
		var canvasHeight = Math.ceil(size.convert(viewBox.height - expandTop + expandBottom));

		canvas.width = canvasWidth;
		canvas.height = canvasHeight;

		// needed for WebKit and full page zoom
		cStyle.width = canvasWidth + 'px';
		cStyle.height = canvasHeight + 'px';

		// minY has no part in canvas.height
		expandTop += viewBox.minY;

		cStyle.top = Math.round(size.convert(expandTop - font.ascent)) + 'px';
		cStyle.left = Math.round(size.convert(expandLeft)) + 'px';

		var wrapperWidth = Math.ceil(size.convert(stretchedWidth)) + 'px';

		if (HAS_INLINE_BLOCK) {
			wStyle.width = wrapperWidth;
			wStyle.height = size.convert(font.height) + 'px';
		}
		else {
			wStyle.paddingLeft = wrapperWidth;
			wStyle.paddingBottom = (size.convert(font.height) - 1) + 'px';
		}

		var g = canvas.getContext('2d'), scale = height / viewBox.height;

		// proper horizontal scaling is performed later
		g.scale(scale, scale * roundingFactor);
		g.translate(-expandLeft, -expandTop);

		g.lineWidth = font.face['underline-thickness'];

		g.save();

		function line(y, color) {
			g.strokeStyle = color;

			g.beginPath();

			g.moveTo(0, y);
			g.lineTo(width, y);

			g.stroke();
		}

		var textDecoration = options.enableTextDecoration ? Cufon.CSS.textDecoration(el, style) : {};

		if (textDecoration.underline) line(-font.face['underline-position'], textDecoration.underline);
		if (textDecoration.overline) line(font.ascent, textDecoration.overline);

		function renderText() {
			g.scale(stretchFactor, 1);
			for (var i = 0, j = 0, l = chars.length; i < l; ++i) {
				var glyph = glyphs[chars[i]] || font.missingGlyph;
				if (!glyph) continue;
				if (glyph.d) {
					g.beginPath();
					if (glyph.code) interpret(glyph.code, g);
					else glyph.code = generateFromVML('m' + glyph.d, g);
					g.fill();
				}
				g.translate(jumps[j++], 0);
			}
			g.restore();
		}

		if (shadows) {
			for (var i = shadows.length; i--;) {
				var shadow = shadows[i];
				g.save();
				g.fillStyle = shadow.color;
				g.translate.apply(g, shadowOffsets[i]);
				renderText();
			}
		}

		var gradient = options.textGradient;
		if (gradient) {
			var stops = gradient.stops, fill = g.createLinearGradient(0, viewBox.minY, 0, viewBox.maxY);
			for (var i = 0, l = stops.length; i < l; ++i) {
				fill.addColorStop.apply(fill, stops[i]);
			}
			g.fillStyle = fill;
		}
		else g.fillStyle = style.get('color');

		renderText();

		if (textDecoration['line-through']) line(-font.descent, textDecoration['line-through']);

		return wrapper;

	};

})());

Cufon.registerEngine('vml', (function() {

	var ns = document.namespaces;
	if (!ns) return;
	ns.add('cvml', 'urn:schemas-microsoft-com:vml');
	ns = null;

	var check = document.createElement('cvml:shape');
	check.style.behavior = 'url(#default#VML)';
	if (!check.coordsize) return; // VML isn't supported
	check = null;

	var HAS_BROKEN_LINEHEIGHT = (document.documentMode || 0) < 8;

	document.write(('<style type="text/css">' +
		'.cufon-vml-canvas{text-indent:0;}' +
		'@media screen{' +
			'cvml\\:shape,cvml\\:rect,cvml\\:fill,cvml\\:shadow{behavior:url(#default#VML);display:block;antialias:true;position:absolute;}' +
			'.cufon-vml-canvas{position:absolute;text-align:left;}' +
			'.cufon-vml{display:inline-block;position:relative;vertical-align:' +
			(HAS_BROKEN_LINEHEIGHT
				? 'middle'
				: 'text-bottom') +
			';}' +
			'.cufon-vml .cufon-alt{position:absolute;left:-10000in;font-size:1px;}' +
			'a .cufon-vml{cursor:pointer}' + // ignore !important here
		'}' +
		'@media print{' +
			'.cufon-vml *{display:none;}' +
			'.cufon-vml .cufon-alt{display:inline;}' +
		'}' +
	'</style>').replace(/;/g, '!important;'));

	function getFontSizeInPixels(el, value) {
		return getSizeInPixels(el, /(?:em|ex|%)$|^[a-z-]+$/i.test(value) ? '1em' : value);
	}

	// Original by Dead Edwards.
	// Combined with getFontSizeInPixels it also works with relative units.
	function getSizeInPixels(el, value) {
		if (/px$/i.test(value)) return parseFloat(value);
		var style = el.style.left, runtimeStyle = el.runtimeStyle.left;
		el.runtimeStyle.left = el.currentStyle.left;
		el.style.left = value.replace('%', 'em');
		var result = el.style.pixelLeft;
		el.style.left = style;
		el.runtimeStyle.left = runtimeStyle;
		return result;
	}

	var fills = {};

	function gradientFill(gradient) {
		var id = gradient.id;
		if (!fills[id]) {
			var stops = gradient.stops, fill = document.createElement('cvml:fill'), colors = [];
			fill.type = 'gradient';
			fill.angle = 180;
			fill.focus = '0';
			fill.method = 'sigma';
			fill.color = stops[0][1];
			for (var j = 1, k = stops.length - 1; j < k; ++j) {
				colors.push(stops[j][0] * 100 + '% ' + stops[j][1]);
			}
			fill.colors = colors.join(',');
			fill.color2 = stops[k][1];
			fills[id] = fill;
		}
		return fills[id];
	}

	return function(font, text, style, options, node, el, hasNext) {

		var redraw = (text === null);

		if (redraw) text = node.alt;

		// @todo word-spacing, text-decoration

		var viewBox = font.viewBox;

		var size = style.computedFontSize || (style.computedFontSize = new Cufon.CSS.Size(getFontSizeInPixels(el, style.get('fontSize')) + 'px', font.baseSize));

		var letterSpacing = style.computedLSpacing;

		if (letterSpacing == undefined) {
			letterSpacing = style.get('letterSpacing');
			style.computedLSpacing = letterSpacing = (letterSpacing == 'normal') ? 0 : ~~size.convertFrom(getSizeInPixels(el, letterSpacing));
		}

		var wrapper, canvas;

		if (redraw) {
			wrapper = node;
			canvas = node.firstChild;
		}
		else {
			wrapper = document.createElement('span');
			wrapper.className = 'cufon cufon-vml';
			wrapper.alt = text;

			canvas = document.createElement('span');
			canvas.className = 'cufon-vml-canvas';
			wrapper.appendChild(canvas);

			if (options.printable) {
				var print = document.createElement('span');
				print.className = 'cufon-alt';
				print.appendChild(document.createTextNode(text));
				wrapper.appendChild(print);
			}

			// ie6, for some reason, has trouble rendering the last VML element in the document.
			// we can work around this by injecting a dummy element where needed.
			// @todo find a better solution
			if (!hasNext) wrapper.appendChild(document.createElement('cvml:shape'));
		}

		var wStyle = wrapper.style;
		var cStyle = canvas.style;

		var height = size.convert(viewBox.height), roundedHeight = Math.ceil(height);
		var roundingFactor = roundedHeight / height;
		var stretchFactor = roundingFactor * Cufon.CSS.fontStretch(style.get('fontStretch'));
		var minX = viewBox.minX, minY = viewBox.minY;

		cStyle.height = roundedHeight;
		cStyle.top = Math.round(size.convert(minY - font.ascent));
		cStyle.left = Math.round(size.convert(minX));

		wStyle.height = size.convert(font.height) + 'px';

		var textDecoration = options.enableTextDecoration ? Cufon.CSS.textDecoration(el, style) : {};

		var color = style.get('color');
		var chars = Cufon.CSS.textTransform(text, style).split(''), chr;

		var glyphs = font.glyphs, glyph, kerning, k;
		var width = 0, jumps = [], offsetX = 0, advance;

		var shape, shadows = options.textShadow;

		// pre-calculate width
		for (var i = 0, j = 0, l = chars.length; i < l; ++i) {
			glyph = glyphs[chr = chars[i]] || font.missingGlyph;
			if (!glyph) continue;
			if (kerning) {
				width -= k = kerning[chr] || 0;
				jumps[j - 1] -= k;
			}
			width += advance = jumps[j++] = ~~(glyph.w || font.w) + letterSpacing;
			kerning = glyph.k;
		}

		if (advance === undefined) return null;

		var fullWidth = -minX + width + (viewBox.width - advance);

		var shapeWidth = size.convert(fullWidth * stretchFactor), roundedShapeWidth = Math.round(shapeWidth);

		var coordSize = fullWidth + ',' + viewBox.height, coordOrigin;
		var stretch = 'r' + coordSize + 'ns';

		var fill = options.textGradient && gradientFill(options.textGradient);

		for (i = 0, j = 0; i < l; ++i) {

			glyph = glyphs[chars[i]] || font.missingGlyph;
			if (!glyph) continue;

			if (redraw) {
				// some glyphs may be missing so we can't use i
				shape = canvas.childNodes[j];
				while (shape.firstChild) shape.removeChild(shape.firstChild); // shadow, fill
			}
			else {
				shape = document.createElement('cvml:shape');
				canvas.appendChild(shape);
			}

			shape.stroked = 'f';
			shape.coordsize = coordSize;
			shape.coordorigin = coordOrigin = (minX - offsetX) + ',' + minY;
			shape.path = (glyph.d ? 'm' + glyph.d + 'xe' : '') + 'm' + coordOrigin + stretch;
			shape.fillcolor = color;

			if (fill) shape.appendChild(fill.cloneNode(false));

			// it's important to not set top/left or IE8 will grind to a halt
			var sStyle = shape.style;
			sStyle.width = roundedShapeWidth;
			sStyle.height = roundedHeight;

			if (shadows) {
				// due to the limitations of the VML shadow element there
				// can only be two visible shadows. opacity is shared
				// for all shadows.
				var shadow1 = shadows[0], shadow2 = shadows[1];
				var color1 = Cufon.CSS.color(shadow1.color), color2;
				var shadow = document.createElement('cvml:shadow');
				shadow.on = 't';
				shadow.color = color1.color;
				shadow.offset = shadow1.offX + ',' + shadow1.offY;
				if (shadow2) {
					color2 = Cufon.CSS.color(shadow2.color);
					shadow.type = 'double';
					shadow.color2 = color2.color;
					shadow.offset2 = shadow2.offX + ',' + shadow2.offY;
				}
				shadow.opacity = color1.opacity || (color2 && color2.opacity) || 1;
				shape.appendChild(shadow);
			}

			offsetX += jumps[j++];
		}

		// addresses flickering issues on :hover

		var cover = shape.nextSibling, coverFill, vStyle;

		if (options.forceHitArea) {

			if (!cover) {
				cover = document.createElement('cvml:rect');
				cover.stroked = 'f';
				cover.className = 'cufon-vml-cover';
				coverFill = document.createElement('cvml:fill');
				coverFill.opacity = 0;
				cover.appendChild(coverFill);
				canvas.appendChild(cover);
			}

			vStyle = cover.style;

			vStyle.width = roundedShapeWidth;
			vStyle.height = roundedHeight;

		}
		else if (cover) canvas.removeChild(cover);

		wStyle.width = Math.max(Math.ceil(size.convert(width * stretchFactor)), 0);

		if (HAS_BROKEN_LINEHEIGHT) {

			var yAdjust = style.computedYAdjust;

			if (yAdjust === undefined) {
				var lineHeight = style.get('lineHeight');
				if (lineHeight == 'normal') lineHeight = '1em';
				else if (!isNaN(lineHeight)) lineHeight += 'em'; // no unit
				style.computedYAdjust = yAdjust = 0.5 * (getSizeInPixels(el, lineHeight) - parseFloat(wStyle.height));
			}

			if (yAdjust) {
				wStyle.marginTop = Math.ceil(yAdjust) + 'px';
				wStyle.marginBottom = yAdjust + 'px';
			}

		}

		return wrapper;

	};

})());


/* font */
Cufon.registerFont({"w":180,"face":{"font-family":"Dot Heart","font-weight":400,"font-stretch":"normal","units-per-em":"360","panose-1":"2 0 0 0 0 0 0 0 0 0","ascent":"288","descent":"-72","x-height":"5","bbox":"-2 -276.657 324 77.7594","underline-thickness":"18","underline-position":"-18","unicode-range":"U+0020-U+007D"},"glyphs":{" ":{"w":95},"%":{"d":"175,-99v31,0,51,20,51,51v0,31,-21,51,-52,51v-31,0,-52,-20,-52,-51v0,-31,22,-51,53,-51xm45,7r-18,-10r163,-236r18,11xm61,-234v31,0,52,19,52,50v0,31,-21,51,-52,51v-31,0,-53,-20,-53,-50v0,-31,22,-51,53,-51xm174,-19v16,0,28,-14,28,-29v0,-15,-13,-29,-28,-29v-16,0,-28,14,-29,28v-1,15,13,30,29,30xm60,-154v17,0,29,-13,29,-29v0,-15,-14,-30,-29,-30v-16,0,-28,14,-28,29v0,15,12,30,28,30","w":234},"&":{"d":"150,-186v-1,29,-18,47,-40,62r46,58r17,-19r17,16r-20,23r38,46r-32,0r-21,-27v-31,48,-144,42,-142,-32v1,-39,34,-53,58,-71v-14,-18,-27,-29,-28,-53v-3,-61,108,-65,107,-3xm97,-210v-43,0,-22,52,-4,66v13,-10,33,-21,33,-41v0,-17,-14,-25,-29,-25xm47,-80v-27,35,23,79,65,54v10,-6,20,-12,27,-21r-53,-64v-12,9,-32,22,-39,31","w":208},"(":{"d":"66,-253v-35,72,-34,207,0,279v-8,3,-14,5,-21,9v-39,-77,-37,-226,0,-299v8,4,12,9,21,11","w":87},")":{"d":"44,-264v37,76,36,225,0,299r-21,-9v32,-75,33,-208,-1,-279v9,-2,14,-7,22,-11","w":87},"*":{"d":"89,-191r28,17r-9,17r-29,-17r1,33r-20,0r0,-33r-29,17r-10,-17r29,-17r-28,-16r9,-17r29,17r0,-33r20,0r-1,33r29,-17r10,17","w":138},"+":{"d":"112,-107r0,74r-16,0r0,-74r-73,0r0,-16r73,0r0,-73r16,0r0,73r73,0r0,16r-73,0","w":207},",":{"d":"78,-28r-41,83r-16,-6r29,-85","w":96},"-":{"d":"9,-88r0,-24r80,0r0,24r-80,0","w":98},".":{"d":"48,-33v10,-1,20,8,19,18v1,11,-9,18,-19,18v-9,0,-19,-7,-18,-18v-1,-9,9,-19,18,-18","w":96},"\/":{"d":"127,-257r-87,290r-22,-5r86,-291","w":138},":":{"d":"48,-154v10,0,20,7,19,18v1,10,-10,19,-19,19v-9,0,-19,-9,-18,-19v-1,-11,9,-18,18,-18xm48,-33v10,-1,20,8,19,18v1,11,-9,18,-19,18v-9,0,-19,-7,-18,-18v-1,-9,9,-19,18,-18","w":96},";":{"d":"60,-154v9,0,19,7,18,18v0,10,-8,19,-18,19v-9,0,-19,-10,-19,-19v0,-10,9,-18,19,-18xm35,55r-17,-6r31,-85r27,8","w":109},"=":{"d":"24,-135r0,-17r170,0r0,17r-170,0xm24,-88r0,-17r170,0r0,17r-170,0","w":218},"?":{"d":"75,-244v61,-5,78,83,29,105v-20,9,-53,9,-54,36v-1,14,11,26,25,25v16,-1,24,-10,25,-27r26,0v-1,31,-20,51,-51,51v-30,0,-50,-20,-51,-50v-2,-45,51,-42,75,-64v19,-17,1,-50,-24,-50v-21,0,-37,19,-29,41r-28,0v-5,-40,20,-64,57,-67xm75,-33v11,-1,18,9,18,18v0,11,-8,18,-18,18v-9,0,-19,-7,-18,-18v-1,-9,9,-19,18,-18","w":151},"A":{"d":"183,0r-26,-61r-101,0r-26,61r-30,0r104,-230r7,0r101,230r-29,0xm107,-179r-41,94r82,0","w":212},"B":{"d":"112,-122v27,7,46,26,46,58v0,66,-67,67,-136,64r0,-229v62,-4,115,4,116,61v0,23,-10,36,-26,46xm49,-128v36,2,63,-5,63,-39v0,-33,-26,-42,-63,-39r0,78xm49,-24v43,2,83,-1,83,-41v0,-37,-39,-44,-83,-41r0,82","w":170},"C":{"d":"37,-113v-5,83,104,118,156,67r0,32v-81,46,-183,-5,-183,-100v0,-96,104,-147,183,-101r0,32v-13,-14,-40,-26,-65,-25v-55,2,-88,39,-91,95","w":209},"D":{"d":"22,-229v102,-7,174,21,174,114v0,95,-73,120,-174,115r0,-229xm50,-24v71,3,117,-23,118,-90v1,-70,-46,-92,-118,-90r0,180","w":205},"E":{"d":"22,0r0,-229r120,0r0,25r-92,0r0,67r89,0r0,25r-89,0r0,87r92,0r0,25r-120,0","w":159},"F":{"d":"49,-204r0,67r77,0r0,25r-77,0r0,112r-27,0r0,-229r107,0r0,25r-80,0","w":144},"G":{"d":"37,-114v-10,103,158,131,168,24r-64,0r0,-25r94,0v1,75,-37,119,-109,119v-71,0,-113,-46,-117,-118v-6,-114,155,-160,215,-71v-8,6,-14,10,-21,17v-16,-21,-41,-40,-74,-40v-57,0,-87,39,-92,94","w":244},"H":{"d":"165,0r0,-111r-115,0r0,111r-28,0r0,-229r28,0r0,93r115,0r0,-93r27,0r0,229r-27,0","w":214},"I":{"d":"22,0r0,-229r28,0r0,229r-28,0","w":72},"J":{"d":"81,-57v1,43,-33,70,-76,56r0,-25v29,12,49,-3,49,-42r0,-161r27,0r0,172","w":102},"K":{"d":"150,0r-92,-107r-8,9r0,98r-28,0r0,-229r28,0r0,101r98,-101r35,0r-104,105r108,124r-37,0","w":186},"L":{"d":"22,0r0,-229r28,0r0,204r66,0r0,25r-94,0","w":116},"M":{"d":"8,0r37,-229r10,0r80,179r75,-179r14,0r37,229r-27,0r-24,-160r-67,160r-17,0r-66,-159r-25,159r-27,0","w":268},"N":{"d":"218,0r-168,-177r0,177r-28,0r0,-229r14,0r164,169r0,-169r26,0r1,229r-9,0","w":248},"O":{"d":"130,-233v72,0,119,49,119,119v0,70,-47,118,-120,118v-72,0,-119,-46,-119,-118v0,-72,48,-119,120,-119xm129,-21v56,0,93,-37,93,-93v0,-56,-36,-94,-92,-94v-57,0,-93,38,-93,95v0,56,37,92,92,92","w":258},"P":{"d":"22,-229v66,-2,127,-1,125,65v-1,51,-41,71,-98,66r0,98r-27,0r0,-229xm49,-122v39,3,71,-6,71,-42v0,-36,-31,-44,-71,-41r0,83","w":154},"Q":{"d":"248,-113v0,38,-13,60,-33,82r33,35r-31,0r-20,-21v-74,52,-193,1,-187,-96v4,-72,46,-120,119,-120v73,0,119,48,119,120xm196,-49v15,-16,26,-38,25,-66v-2,-56,-37,-93,-92,-93v-56,0,-90,38,-92,95v-3,73,80,115,142,78r-53,-54r32,0","w":258},"R":{"d":"144,-165v0,37,-24,58,-57,63r73,102r-33,0r-66,-99r-11,0r0,99r-28,0r0,-230v64,-2,122,2,122,65xm50,-122v39,3,68,-9,68,-43v0,-36,-30,-43,-68,-41r0,84","w":165},"S":{"d":"128,-186v-15,-41,-102,-15,-72,25v28,37,99,31,100,95v1,60,-71,89,-118,56v-13,-10,-21,-24,-26,-41r24,-10v3,22,22,42,47,41v27,-1,45,-17,45,-45v0,-61,-104,-40,-105,-107v-1,-66,96,-82,124,-29v-6,7,-12,10,-19,15","w":167},"T":{"d":"84,-204r0,204r-27,0r0,-204r-55,0r0,-25r137,0r0,25r-55,0","w":141},"U":{"d":"187,-82v-1,54,-30,86,-84,86v-54,0,-81,-32,-82,-86r0,-147r27,0v9,80,-31,209,56,209v88,0,47,-130,56,-209r27,0r0,147","w":207},"V":{"d":"109,0r-20,0r-89,-229r31,0r69,175r63,-175r30,0","w":192},"W":{"d":"242,0r-18,0r-64,-170r-62,170r-17,0r-80,-229r30,0r61,170r60,-170r17,0r62,170r62,-170r31,0","w":324},"X":{"d":"143,0r-54,-95r-56,95r-30,0r70,-119r-64,-110r33,0r47,85r49,-85r31,0r-65,110r71,119r-32,0","w":176},"Y":{"d":"179,-229r-77,129r0,100r-27,0r0,-100r-75,-129r32,0r57,99r58,-99r32,0","w":178},"Z":{"d":"49,-25r120,0r0,25r-165,0r122,-204r-106,0r0,-25r151,0","w":174},"[":{"d":"17,35r0,-298r51,0r0,21r-28,0r0,256r28,0r0,21r-51,0","w":76},"]":{"d":"12,35r0,-21r28,0r0,-256r-28,0r0,-21r51,0r0,298r-51,0","w":79},"`":{"d":"89,-177r-12,14r-67,-45r17,-21","w":99},"a":{"d":"9,-75v-7,-73,87,-104,125,-52r0,-22r27,0r0,149r-27,0r0,-22v-36,50,-135,21,-125,-53xm86,-19v32,0,49,-22,49,-56v0,-33,-18,-55,-50,-55v-30,0,-49,23,-49,55v0,33,18,56,50,56","w":182},"b":{"d":"103,-154v45,0,67,34,71,79v6,72,-86,104,-125,54r0,21r-27,0r0,-252r27,0r0,125v12,-15,29,-27,54,-27xm97,-19v32,0,50,-24,50,-56v0,-32,-19,-55,-50,-55v-31,0,-50,23,-50,56v0,32,18,55,50,55","w":182},"c":{"d":"132,-8v-53,30,-123,-2,-123,-66v0,-64,70,-100,122,-67r0,30v-29,-34,-100,-17,-94,37v-6,54,66,69,95,36r0,30","w":146},"d":{"d":"9,-75v-7,-73,87,-104,125,-52r0,-125r27,0r0,252r-27,0r0,-22v-36,52,-134,20,-125,-53xm86,-19v32,0,49,-22,49,-56v0,-33,-18,-55,-50,-55v-30,0,-49,23,-49,55v0,33,18,56,50,56","w":182},"e":{"d":"9,-74v-8,-86,120,-107,141,-30v3,10,3,21,3,33r-116,0v-5,56,71,68,89,24r22,9v-10,25,-34,42,-66,42v-48,-1,-69,-31,-73,-78xm126,-93v-1,-33,-47,-50,-72,-28v-7,7,-13,16,-16,29","w":162},"f":{"d":"22,-149v-5,-52,12,-96,66,-80r0,25v-39,-13,-40,17,-39,55r39,0r0,24r-39,0r0,125r-27,0r0,-125r-14,0r0,-24r14,0","w":88},"h":{"d":"49,-130v26,-39,98,-27,98,37r0,93r-27,0v-6,-49,21,-130,-33,-130v-54,0,-34,79,-38,130r-27,0r0,-252r27,0r0,122","w":168},"i":{"d":"22,-212v-1,-15,20,-26,32,-14v12,11,4,33,-13,33v-9,0,-19,-10,-19,-19xm27,0r0,-149r28,0r0,149r-28,0","w":81},"j":{"d":"41,-231v10,-1,19,10,19,19v0,10,-8,19,-19,19v-9,0,-19,-10,-19,-19v0,-9,9,-20,19,-19xm55,36v1,33,-24,47,-55,40r0,-25v17,4,27,-4,27,-23r0,-177r28,0r0,185","w":81},"k":{"d":"117,0r-59,-69v-16,10,-6,46,-9,69r-27,0r0,-252r27,0r0,161r58,-58r35,0r-65,63r75,86r-35,0","w":151},"l":{"d":"23,0r0,-252r27,0r0,252r-27,0","w":71},"m":{"d":"132,-127v23,-42,95,-31,95,31r0,96r-26,0v-7,-46,18,-129,-29,-129v-51,0,-28,80,-33,129r-27,0v-6,-47,20,-129,-31,-129v-50,0,-27,80,-32,129r-27,0r0,-149r27,0r0,17v17,-28,72,-27,83,5","w":249},"n":{"d":"49,-131v28,-39,98,-24,98,38r0,93r-27,0v-6,-49,21,-130,-33,-130v-54,0,-34,79,-38,130r-27,0r0,-149r27,0r0,18","w":168},"o":{"d":"89,-154v48,0,80,31,80,80v0,48,-32,79,-80,79v-48,0,-80,-31,-80,-79v0,-49,31,-80,80,-80xm89,-20v33,0,52,-23,52,-56v0,-32,-20,-53,-52,-53v-33,0,-52,22,-52,55v0,33,20,54,52,54","w":177},"p":{"d":"102,-154v47,0,69,33,72,80v5,71,-88,104,-125,51r0,95r-27,0r0,-221r27,0r0,22v12,-17,27,-27,53,-27xm97,-19v31,0,50,-24,50,-56v0,-32,-18,-55,-50,-55v-33,0,-50,23,-50,56v0,33,19,55,50,55","w":182},"q":{"d":"9,-74v-7,-72,85,-108,125,-53r0,-22r27,0r0,221r-27,0r0,-95v-36,51,-133,22,-125,-51xm85,-19v32,0,50,-22,50,-56v0,-33,-17,-55,-49,-55v-32,0,-50,23,-50,55v0,32,18,56,49,56","w":178},"r":{"d":"109,-148r-10,24v-61,-24,-50,64,-50,124r-27,0r0,-149r27,0r0,20v9,-20,36,-32,60,-19","w":109},"s":{"d":"45,-113v8,33,69,24,69,69v0,59,-89,64,-102,15v7,-5,11,-7,19,-11v7,24,59,31,57,-5v-13,-33,-69,-22,-69,-67v0,-43,69,-56,85,-17r-19,12v-8,-19,-40,-19,-40,4","w":126},"t":{"d":"50,-125v6,36,-20,111,29,99r0,26v-36,6,-57,-9,-56,-46r0,-79r-14,0r0,-24r14,0r0,-55r27,0r0,55r28,0r0,24r-28,0","w":78},"u":{"d":"144,-149v-1,71,15,153,-62,153v-75,0,-60,-83,-61,-153r27,0v5,50,-20,128,35,128v54,0,28,-80,34,-128r27,0","w":164},"v":{"d":"80,0r-12,0r-69,-149r31,0r45,98r43,-98r30,0","w":146},"w":{"d":"173,0r-10,0r-42,-101r-43,101r-12,0r-67,-149r31,0r44,99r43,-99r9,0r41,100r46,-100r30,0","w":241},"x":{"d":"129,0r-49,-61r-48,61r-33,0r65,-80r-56,-69r34,0r38,49r39,-49r33,0r-55,69r65,80r-33,0","w":160},"y":{"d":"51,72r-31,0r47,-89r-69,-132r32,0r52,102r48,-102r30,0","w":158},"z":{"d":"117,-139r-69,115r73,0r0,24r-110,0r0,-10r67,-115r-59,0r0,-24r98,0r0,10","w":129},"{":{"d":"186,-247v-43,-20,-42,37,-39,85r0,13r39,0r0,23r-39,0r0,126r-27,0r0,-126r-71,0r0,126r-27,0r0,-126r-14,0r0,-23r14,0v-3,-66,1,-128,64,-127v18,0,33,7,45,21v9,-19,30,-26,55,-19r0,27xm86,-253v-45,1,-36,56,-37,104r71,0v-2,-44,12,-104,-34,-104","w":186},"|":{"d":"219,0r0,-149r26,0r0,149r-26,0xm134,-249v33,-53,127,-22,111,54r-26,0v0,-32,-9,-61,-42,-57v-40,5,-28,60,-30,103r39,0r0,23r-39,0r0,126r-27,0r0,-126r-71,0r0,126r-27,0r0,-126r-14,0r0,-23r14,0v-1,-60,-2,-126,63,-127v24,0,40,11,49,27xm85,-253v-45,1,-35,59,-36,104r72,0v-4,-43,11,-105,-36,-104","w":267},"}":{"d":"134,-249v32,-53,126,-22,111,52r0,197r-26,0r-1,-209v0,-27,-9,-44,-35,-44v-44,0,-36,58,-36,104r39,0r0,23r-39,0r0,126r-27,0r0,-126r-71,0r0,126r-27,0r0,-126r-14,0r0,-23r14,0v-1,-64,0,-129,63,-127v24,0,40,11,49,27xm85,-253v-44,1,-35,59,-36,104r72,0v-4,-43,11,-105,-36,-104","w":267},"$":{"d":"86,-115v-54,-8,-73,-110,0,-118r0,-28r20,0r0,28v25,4,37,15,48,33r-20,12v-8,-12,-14,-18,-28,-23r0,79v28,12,57,28,57,65v0,39,-24,61,-57,68r0,31r-20,0r0,-30v-37,-5,-57,-23,-66,-57v37,-16,26,37,66,36r0,-96xm86,-211v-24,3,-38,35,-22,55v5,6,12,11,22,16r0,-71xm106,-21v30,-3,45,-50,21,-72r-21,-14r0,86","w":183},"!":{"d":"37,-54r0,-186r30,0r0,186r-30,0xm52,-33v10,-1,19,9,19,18v0,10,-9,18,-19,18v-11,0,-18,-7,-18,-18v0,-9,7,-19,18,-18","w":104},"<":{"d":"80,-44r-16,13r-54,-69r54,-70r16,13r-44,57","w":101},">":{"d":"93,-100r-54,69r-16,-13r44,-56r-44,-57r16,-13","w":103},"0":{"d":"90,-229v57,0,80,54,80,116v0,63,-23,117,-80,117v-57,0,-80,-54,-80,-116v0,-63,23,-117,80,-117xm90,-19v75,-9,75,-178,0,-187v-74,9,-73,178,0,187"},"1":{"d":"87,0r0,-201r-34,0r0,-24r61,0r0,225r-27,0"},"2":{"d":"90,-229v54,0,89,51,63,99v-21,39,-56,75,-84,106r92,0r0,24r-146,0r54,-62v23,-30,58,-55,66,-101v-2,-25,-17,-42,-44,-42v-27,0,-43,19,-45,44r-27,0v3,-42,26,-68,71,-68"},"3":{"d":"122,-118v22,7,34,28,36,55v5,74,-107,90,-133,32v-4,-7,-6,-16,-6,-25r25,0v4,22,20,37,44,37v27,0,43,-17,44,-44v0,-29,-17,-44,-47,-44r0,-22v26,0,44,-13,44,-38v0,-22,-16,-39,-39,-39v-21,0,-35,12,-39,35r-25,0v5,-36,26,-56,64,-58v64,-4,87,89,32,111"},"4":{"d":"141,-37r0,37r-25,0r0,-37r-115,0r129,-188r11,0r0,165r28,0r0,23r-28,0xm116,-165r-72,105r72,0r0,-105"},"5":{"d":"134,-76v0,-49,-62,-71,-91,-40r-7,-2r31,-107r91,0r0,24r-72,0r-15,51v51,-11,88,23,90,74v3,83,-112,107,-152,44r18,-18v21,46,107,38,107,-26"},"6":{"d":"71,-140v51,-18,96,17,96,67v0,47,-31,74,-78,77v-71,3,-92,-80,-54,-133r72,-101v8,3,14,6,21,11xm89,-20v30,0,51,-21,51,-51v0,-31,-20,-52,-51,-52v-31,0,-49,23,-52,52v3,29,21,51,52,51"},"7":{"d":"180,-225r-145,229v-8,-4,-15,-8,-22,-11r123,-194r-120,0r0,-24r164,0"},"8":{"d":"112,-127v26,7,45,30,45,62v0,43,-29,66,-70,69v-76,6,-93,-115,-24,-131v-21,-8,-35,-25,-35,-50v0,-34,26,-54,59,-56v62,-5,81,89,25,106xm87,-139v20,0,34,-17,34,-36v0,-19,-15,-36,-34,-36v-18,0,-33,18,-33,36v0,19,15,36,33,36xm87,-20v29,0,44,-19,44,-48v0,-28,-18,-46,-44,-46v-26,0,-43,20,-43,46v0,27,14,48,43,48","w":171},"9":{"d":"91,-228v70,-3,93,80,54,134r-72,99r-22,-11r58,-79v-49,17,-97,-16,-95,-67v2,-47,31,-74,77,-76xm91,-102v32,0,52,-20,52,-51v0,-31,-21,-52,-52,-52v-31,0,-51,21,-51,52v0,30,21,51,51,51"},"@":{"d":"59,-77v-7,-61,77,-84,109,-43r0,-19r25,0r0,88v0,12,4,21,15,22v18,-5,22,-29,22,-51v0,-64,-41,-103,-103,-103v-62,0,-103,41,-103,103v0,76,75,123,151,94r6,16v-83,38,-180,-18,-176,-110v3,-74,48,-120,122,-122v88,-2,136,70,117,159v-6,27,-41,45,-65,24v-5,-5,-6,-9,-6,-17v-29,48,-123,25,-114,-41xm125,-33v28,0,45,-15,45,-44v0,-28,-18,-43,-45,-43v-26,0,-41,16,-41,44v-1,28,17,42,41,43","w":254},"g":{"d":"12,-80v-7,-69,87,-97,122,-49r0,-20r27,0v-3,104,28,259,-104,220v-26,-8,-42,-30,-45,-62r28,0v2,24,20,43,46,43v45,0,50,-35,48,-81v-33,46,-132,18,-122,-51xm87,-29v29,0,47,-21,47,-49v0,-30,-16,-52,-47,-52v-30,0,-48,21,-48,51v0,30,17,49,48,50","w":168},"\u00a0":{"w":95}}});