{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350
{\fonttbl\f0\fmodern\fcharset0 Courier;}
{\colortbl;\red255\green255\blue255;}
\paperw11900\paperh16840\margl1440\margr1440\vieww9000\viewh8400\viewkind0
\deftab720
\pard\pardeftab720\ql\qnatural

\f0\fs24 \cf0 /*!\
 * Copyright (c) 2011 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;\
		\},\
\
		strict: (function() \{\
			var doctype;\
			// no doctype (doesn't always catch it though.. IE I'm looking at you)\
			if (document.compatMode == 'BackCompat') return false;\
			// WebKit, Gecko, Opera, IE9+\
			doctype = document.doctype;\
			if (doctype) \{\
				return !/frameset|transitional/i.test(doctype.publicId);\
			\}\
			// IE<9, firstChild is the doctype even if there's an XML declaration\
			doctype = document.firstChild;\
			if (doctype.nodeType != 8 || /^DOCTYPE.+(transitional|frameset)/i.test(doctype.data)) \{\
				return false;\
			\}\
			return true;\
		\})()\
\
	\};\
\
	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;\
		\}),\
\
		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;\
		\},\
\
		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(/(?:^|\\s)./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\
			\};\
			var wsStart = /^\\s+/, wsEnd = /\\s+$/;\
			return function(text, style, node, previousElement, simple) \{\
				if (simple) return text.replace(wsStart, '').replace(wsEnd, ''); // @fixme too simple\
				if (previousElement) \{\
					if (previousElement.nodeName.toLowerCase() == 'br') \{\
						text = text.replace(wsStart, '');\
					\}\
				\}\
				if (ignore[style.get('display')]) return text;\
				if (!node.previousSibling) text = text.replace(wsStart, '');\
				if (!node.nextSibling) text = text.replace(wsEnd, '');\
				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');\
\
		var checkTypes = \{\
			'': 1,\
			'text/css': 1\
		\};\
\
		function isContainerReady(el) \{\
			if (!checkTypes[el.type.toLowerCase()]) return true;\
			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, wordSeparators = \{\
			'\\u0020': 1,\
			'\\u00a0': 1,\
			'\\u3000': 1\
		\};\
\
		this.glyphs = (function(glyphs) \{\
			var key, fallbacks = \{\
				'\\u2011': '\\u002d',\
				'\\u00ad': '\\u2011'\
			\};\
			for (key in fallbacks) \{\
				if (!hasOwnProperty(fallbacks, key)) continue;\
				if (!glyphs[key]) glyphs[key] = glyphs[fallbacks[key]];\
			\}\
			return 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;\
\
		this.spacing = function(chars, letterSpacing, wordSpacing) \{\
			var glyphs = this.glyphs, glyph,\
				kerning, k,\
				jumps = [],\
				width = 0, w,\
				i = -1, j = -1, chr;\
			while (chr = chars[++i]) \{\
				glyph = glyphs[chr] || this.missingGlyph;\
				if (!glyph) continue;\
				if (kerning) \{\
					width -= k = kerning[chr] || 0;\
					jumps[j] -= k;\
				\}\
				w = glyph.w;\
				if (isNaN(w)) w = +this.w; // may have been a String in old fonts\
				if (w > 0) \{\
					w += letterSpacing;\
					if (wordSeparators[chr]) w += wordSpacing;\
				\}\
				width += jumps[++j] = ~~w; // get rid of decimals\
				kerning = glyph.k;\
			\}\
			jumps.total = width;\
			return jumps;\
		\};\
\
	\}\
\
	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) \{\
			try \{\
				if (node.contains) return node.contains(anotherNode);\
				return node.compareDocumentPosition(anotherNode) & 16;\
			\}\
			catch(e) \{\} // probably a XUL element such as a scrollbar\
			return false;\
		\}\
\
		// mouseover/mouseout (standards) mode\
		function onOverOut(e) \{\
			var related = e.relatedTarget;\
			// there might be no relatedTarget if the element is right next\
			// to the window frame\
			if (related && contains(this, related)) return;\
			trigger(this, e.type == 'mouseover');\
		\}\
\
		// mouseenter/mouseleave (probably ie) mode\
		function onEnterLeave(e) \{\
			if (!e) e = window.event;\
			// ie model, we don't have access to "this", but\
			// mouseenter/leave doesn't bubble so it's fine.\
			trigger(e.target || e.srcElement, e.type == 'mouseenter');\
		\}\
\
		function trigger(el, hoverState) \{\
			// 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() \{\
				var options = sharedStorage.get(el).options;\
				if (hoverState) \{\
					options = merge(options, options.hover);\
					options._mediatorMode = 1;\
				\}\
				api.replace(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);\
			\}\
		\};\
\
		this.detach = function(el) \{\
			if (el.onmouseenter === undefined) \{\
				removeEvent(el, 'mouseover', onOverOut);\
				removeEvent(el, 'mouseout', onOverOut);\
			\}\
			else \{\
				removeEvent(el, 'mouseenter', onEnterLeave);\
				removeEvent(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) \{\
			// we don't really need "this" right now, saves code\
			el.attachEvent('on' + type, listener);\
		\}\
	\}\
\
	function attach(el, options) \{\
		if (options._mediatorMode) return el;\
		var storage = sharedStorage.get(el);\
		var oldOptions = storage.options;\
		if (oldOptions) \{\
			if (oldOptions === options) return el;\
			if (oldOptions.hover) hoverHandler.detach(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 = \{\}, arg, key;\
		for (var i = 0, l = arguments.length; arg = arguments[i], i < l; ++i) \{\
			for (key in arg) \{\
				if (hasOwnProperty(arg, key)) merged[key] = arg[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 removeEvent(el, type, listener) \{\
		if (el.removeEventListener) \{\
			el.removeEventListener(type, listener, false);\
		\}\
		else if (el.detachEvent) \{\
			el.detachEvent('on' + type, listener);\
		\}\
	\}\
\
	function replaceElement(el, options) \{\
		var name = el.nodeName.toLowerCase();\
		if (options.ignore[name]) return;\
		if (options.ignoreClass && options.ignoreClass.test(el.className)) return;\
		if (options.onBeforeReplace) options.onBeforeReplace(el, options);\
		var replace = !options.textless[name], simple = (options.trim === 'simple');\
		var style = CSS.getStyle(attach(el, options)).extend(options);\
		// may cause issues if the element contains other elements\
		// with larger fontSize, however such cases are rare and can\
		// be fixed by using a more specific selector\
		if (parseFloat(style.get('fontSize')) === 0) return;\
		var font = getFont(el, style), node, type, next, anchor, text, lastElement;\
		var isShy = options.softHyphens, anyShy = false, pos, shy, reShy = /\\u00ad/g;\
		var modifyText = options.modifyText;\
		if (!font) return;\
		for (node = el.firstChild; node; node = next) \{\
			type = node.nodeType;\
			next = node.nextSibling;\
			if (replace && type == 3) \{\
				if (isShy && el.nodeName.toLowerCase() != TAG_SHY) \{\
					pos = node.data.indexOf('\\u00ad');\
					if (pos >= 0) \{\
						node.splitText(pos);\
						next = node.nextSibling;\
						next.deleteData(0, 1);\
						shy = document.createElement(TAG_SHY);\
						shy.appendChild(document.createTextNode('\\u00ad'));\
						el.insertBefore(shy, next);\
						next = shy;\
						anyShy = true;\
					\}\
				\}\
				// 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) \{\
				text = anchor.data;\
				if (!isShy) text = text.replace(reShy, '');\
				text = CSS.whiteSpace(text, style, anchor, lastElement, simple);\
				// modify text only on the first replace\
				if (modifyText) text = modifyText(text, anchor, el, options);\
				el.replaceChild(process(font, text, style, options, node, el), anchor);\
				anchor = null;\
			\}\
			if (type == 1) \{\
				if (node.firstChild) \{\
					if (node.nodeName.toLowerCase() == 'cufon') \{\
						engines[options.engine](font, null, style, options, node, el);\
					\}\
					else arguments.callee(node, options);\
				\}\
				lastElement = node;\
			\}\
		\}\
		if (isShy && anyShy) \{\
			updateShy(el);\
			if (!trackingShy) addEvent(window, 'resize', updateShyOnResize);\
			trackingShy = true;\
		\}\
		if (options.onAfterReplace) options.onAfterReplace(el, options);\
	\}\
\
	function updateShy(context) \{\
		var shys, shy, parent, glue, newGlue, next, prev, i;\
		shys = context.getElementsByTagName(TAG_SHY);\
		// unfortunately there doesn't seem to be any easy\
		// way to avoid having to loop through the shys twice.\
		for (i = 0; shy = shys[i]; ++i) \{\
			shy.className = C_SHY_DISABLED;\
			glue = parent = shy.parentNode;\
			if (glue.nodeName.toLowerCase() != TAG_GLUE) \{\
				newGlue = document.createElement(TAG_GLUE);\
				newGlue.appendChild(shy.previousSibling);\
				parent.insertBefore(newGlue, shy);\
				newGlue.appendChild(shy);\
			\}\
			else \{\
				// get rid of double glue (edge case fix)\
				glue = glue.parentNode;\
				if (glue.nodeName.toLowerCase() == TAG_GLUE) \{\
					parent = glue.parentNode;\
					while (glue.firstChild) \{\
						parent.insertBefore(glue.firstChild, glue);\
					\}\
					parent.removeChild(glue);\
				\}\
			\}\
		\}\
		for (i = 0; shy = shys[i]; ++i) \{\
			shy.className = '';\
			glue = shy.parentNode;\
			parent = glue.parentNode;\
			next = glue.nextSibling || parent.nextSibling;\
			// make sure we're comparing same types\
			prev = (next.nodeName.toLowerCase() == TAG_GLUE) ? glue : shy.previousSibling;\
			if (prev.offsetTop >= next.offsetTop) \{\
				shy.className = C_SHY_DISABLED;\
				if (prev.offsetTop < next.offsetTop) \{\
					// we have an annoying edge case, double the glue\
					newGlue = document.createElement(TAG_GLUE);\
					parent.insertBefore(newGlue, glue);\
					newGlue.appendChild(glue);\
					newGlue.appendChild(next);\
				\}\
			\}\
		\}\
	\}\
\
	function updateShyOnResize() \{\
		if (ignoreResize) return; // needed for IE\
		CSS.addClass(DOM.root(), C_VIEWPORT_RESIZING);\
		clearTimeout(shyTimer);\
		shyTimer = setTimeout(function() \{\
			ignoreResize = true;\
			CSS.removeClass(DOM.root(), C_VIEWPORT_RESIZING);\
			updateShy(document);\
			ignoreResize = false;\
		\}, 100);\
	\}\
\
	var HAS_BROKEN_REGEXP = ' '.split(/\\s+/).length == 0;\
	var TAG_GLUE = 'cufonglue';\
	var TAG_SHY = 'cufonshy';\
	var C_SHY_DISABLED = 'cufon-shy-disabled';\
	var C_VIEWPORT_RESIZING = 'cufon-viewport-resizing';\
\
	var sharedStorage = new Storage();\
	var hoverHandler = new HoverHandler();\
	var replaceHistory = new ReplaceHistory();\
	var initialized = false;\
	var trackingShy = false;\
	var shyTimer;\
	var ignoreResize = false;\
\
	var engines = \{\}, fonts = \{\}, defaultOptions = \{\
		autoDetect: false,\
		engine: null,\
		forceHitArea: false,\
		hover: false,\
		hoverables: \{\
			a: true\
		\},\
		ignore: \{\
			applet: 1,\
			canvas: 1,\
			col: 1,\
			colgroup: 1,\
			head: 1,\
			iframe: 1,\
			map: 1,\
			noscript: 1,\
			optgroup: 1,\
			option: 1,\
			script: 1,\
			select: 1,\
			style: 1,\
			textarea: 1,\
			title: 1,\
			pre: 1\
		\},\
		ignoreClass: null,\
		modifyText: null,\
		onAfterReplace: null,\
		onBeforeReplace: null,\
		printable: true,\
		selector: (\
				window.Sizzle\
			||	(window.jQuery && function(query) \{ return jQuery(query); \}) // avoid noConflict issues\
			||	(window.dojo && dojo.query)\
			||	(window.glow && glow.dom && glow.dom.get)\
			||	(window.Ext && Ext.query)\
			||	(window.YAHOO && YAHOO.util && YAHOO.util.Selector && YAHOO.util.Selector.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\
		softHyphens: true,\
		textless: \{\
			dl: 1,\
			html: 1,\
			ol: 1,\
			table: 1,\
			tbody: 1,\
			thead: 1,\
			tfoot: 1,\
			tr: 1,\
			ul: 1\
		\},\
		textShadow: 'none',\
		trim: 'advanced'\
	\};\
\
	var separators = \{\
		// The first pattern may cause unicode characters above\
		// code point 255 to be removed in Safari 3.0. Luckily enough\
		// Safari 3.0 does not include non-breaking spaces in \\s, so\
		// we can just use a simple alternative pattern.\
		words: /\\s/.test('\\u00a0') ? /[^\\S\\u00a0]+/ : /\\s+/,\
		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) \{\
		if (!data) return api;\
		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 (options.autoDetect) delete options.fontFamily;\
		if (typeof options.ignoreClass == 'string') \{\
			options.ignoreClass = new RegExp('(?:^|\\\\s)(?:' + options.ignoreClass.replace(/\\s+/g, '|') + ')(?:\\\\s|$)');\
		\}\
		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);\
		\}\
		else delete options.textGradient;\
		if (typeof elements == 'string') \{\
			if (!ignoreHistory) replaceHistory.add(elements, arguments);\
			elements = [ elements ];\
		\}\
		else if (elements.nodeType) 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('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">' +\
		'cufoncanvas\{text-indent:0;\}' +\
		'@media screen\{' +\
			'cvml\\\\:shape,cvml\\\\:rect,cvml\\\\:fill,cvml\\\\:shadow\{behavior:url(#default#VML);display:block;antialias:true;position:absolute;\}' +\
			'cufoncanvas\{position:absolute;text-align:left;\}' +\
			'cufon\{display:inline-block;position:relative;vertical-align:' +\
			(HAS_BROKEN_LINEHEIGHT\
				? 'middle'\
				: 'text-bottom') +\
			';\}' +\
			'cufon cufontext\{position:absolute;left:-10000in;font-size:1px;text-align:left;\}' +\
			'cufonshy.cufon-shy-disabled,.cufon-viewport-resizing cufonshy\{display:none;\}' +\
			'cufonglue\{white-space:nowrap;display:inline-block;\}' +\
			'.cufon-viewport-resizing cufonglue\{white-space:normal;\}' +\
			'a cufon\{cursor:pointer\}' + // ignore !important here\
		'\}' +\
		'@media print\{' +\
			'cufon cufoncanvas\{display:none;\}' +\
		'\}' +\
	'</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 (!isNaN(value) || /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;\
	\}\
\
	function getSpacingValue(el, style, size, property) \{\
		var key = 'computed' + property, value = style[key];\
		if (isNaN(value)) \{\
			value = style.get(property);\
			style[key] = value = (value == 'normal') ? 0 : ~~size.convertFrom(getSizeInPixels(el, value));\
		\}\
		return value;\
	\}\
\
	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 = 'none';\
			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;\
\
		var viewBox = font.viewBox;\
\
		var size = style.computedFontSize || (style.computedFontSize = new Cufon.CSS.Size(getFontSizeInPixels(el, style.get('fontSize')) + 'px', font.baseSize));\
\
		var wrapper, canvas;\
\
		if (redraw) \{\
			wrapper = node;\
			canvas = node.firstChild;\
		\}\
		else \{\
			wrapper = document.createElement('cufon');\
			wrapper.className = 'cufon cufon-vml';\
			wrapper.alt = text;\
\
			canvas = document.createElement('cufoncanvas');\
			wrapper.appendChild(canvas);\
\
			if (options.printable) \{\
				var print = document.createElement('cufontext');\
				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 color = style.get('color');\
		var chars = Cufon.CSS.textTransform(text, style).split('');\
\
		var jumps = font.spacing(chars,\
			getSpacingValue(el, style, size, 'letterSpacing'),\
			getSpacingValue(el, style, size, 'wordSpacing')\
		);\
\
		if (!jumps.length) return null;\
\
		var width = jumps.total;\
		var fullWidth = -minX + width + (viewBox.width - jumps[jumps.length - 1]);\
\
		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);\
\
		var glyphs = font.glyphs, offsetX = 0;\
		var shadows = options.textShadow;\
		var i = -1, j = 0, chr;\
\
		while (chr = chars[++i]) \{\
\
			var glyph = glyphs[chars[i]] || font.missingGlyph, shape;\
			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;\
\
	\};\
\
\})());\
\
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\{text-indent:0;\}' +\
		'@media screen,projection\{' +\
			'cufon\{display:inline;display:inline-block;position:relative;vertical-align:middle;' +\
			(HAS_BROKEN_LINEHEIGHT\
				? ''\
				: 'font-size:1px;line-height:1px;') +\
			'\}cufon cufontext\{display:-moz-inline-box;display:inline-block;width:0;height:0;text-align:left;text-indent:-10000in;\}' +\
			(HAS_INLINE_BLOCK\
				? 'cufon canvas\{position:relative;\}'\
				: 'cufon canvas\{position:absolute;\}') +\
			'cufonshy.cufon-shy-disabled,.cufon-viewport-resizing cufonshy\{display:none;\}' +\
			'cufonglue\{white-space:nowrap;display:inline-block;\}' +\
			'.cufon-viewport-resizing cufonglue\{white-space:normal;\}' +\
		'\}' +\
		'@media print\{' +\
			'cufon\{padding:0;\}' + // Firefox 2\
			'cufon canvas\{display:none;\}' +\
		'\}'\
	).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.getAttribute('alt');\
\
		var viewBox = font.viewBox;\
\
		var size = style.getSize('fontSize', font.baseSize);\
\
		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('');\
\
		var jumps = font.spacing(chars,\
			~~size.convertFrom(parseFloat(style.get('letterSpacing')) || 0),\
			~~size.convertFrom(parseFloat(style.get('wordSpacing')) || 0)\
		);\
\
		if (!jumps.length) return null; // there's nothing to render\
\
		var width = jumps.total;\
\
		expandRight += viewBox.width - jumps[jumps.length - 1];\
		expandLeft += viewBox.minX;\
\
		var wrapper, canvas;\
\
		if (redraw) \{\
			wrapper = node;\
			canvas = node.firstChild;\
		\}\
		else \{\
			wrapper = document.createElement('cufon');\
			wrapper.className = 'cufon cufon-canvas';\
			wrapper.setAttribute('alt', text);\
\
			canvas = document.createElement('canvas');\
			wrapper.appendChild(canvas);\
\
			if (options.printable) \{\
				var print = document.createElement('cufontext');\
				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.max(Math.ceil(size.convert(stretchedWidth)), 0) + '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;\
		var pixelRatio = window.devicePixelRatio || 1;\
		if (pixelRatio != 1) \{\
			canvas.width = canvasWidth * pixelRatio;\
			canvas.height = canvasHeight * pixelRatio;\
			g.scale(pixelRatio, pixelRatio);\
		\}\
\
		// proper horizontal scaling is performed later\
		g.scale(scale, scale * roundingFactor);\
		g.translate(-expandLeft, -expandTop);\
		g.save();\
\
		function renderText() \{\
			var glyphs = font.glyphs, glyph, i = -1, j = -1, chr;\
			g.scale(stretchFactor, 1);\
			while (chr = chars[++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();\
\
		return wrapper;\
\
	\};\
\
\})());}
