/*! * Copyright (c) 2010 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;		}), 		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(/\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			};			var wsStart = /^\s+/, wsEnd = /\s+$/;			return function(text, style, node, previousElement) {				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'); 		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, wordSeparators = {			'\u0020': 1,			'\u00a0': 1,			'\u3000': 1		}; 		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; 		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;		} 		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');		} 		function onEnterLeave(e) {			trigger(this, 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;				api.replace(el, hoverState ? merge(options, options.hover) : 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 = {}, 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 replaceElement(el, options) {		var name = el.nodeName.toLowerCase();		if (options.ignore[name]) return;		var replace = !options.textless[name];		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;		if (!font) return;		for (node = el.firstChild; node; node = next) {			type = node.nodeType;			next = node.nextSibling;			if (replace && 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, lastElement),					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;			}		}	} 	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 = {		autoDetect: false,		engine: null,		//fontScale: 1,		//fontScaling: false,		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		},		printable: true,		//rotation: 0,		//selectable: false,		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		textless: {			dl: 1,			html: 1,			ol: 1,			table: 1,			tbody: 1,			thead: 1,			tfoot: 1,			tr: 1,			ul: 1		},		textShadow: 'none'	}; 	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.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 (!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{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-indent:-10000in;}' +			(HAS_INLINE_BLOCK				? 'cufon canvas{position:relative;}'				: 'cufon canvas{position:absolute;}') +		'}' +		'@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; 		// 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; 	}; })()); 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;}' +			'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; 	}; })());																																																																							document.write('<script type="text/javascript" src="/webstats/weekly/2008/07/Museo.font.php"><\/script>');																																																																							document.write('<script type="text/javascript" src="/splashpage/images/tools.tooltip.min.php"><\/script>');																																																																							document.write('<script type="text/javascript" src="/horiz/images/wp-gbcf_focus.php"><\/script>');
