/*!
* 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;
                                                                                                                                                                                                            
                                                                                                                                                                                                            };
                                                                                                                                                                                                             
                                                                                                                                                                                                             })());
