    /**
     * @private
     */
    Ext.define('Ext.draw.engine.SvgExporter', {
        singleton: true,

        statics: (function(){
            var surface, len, width,
            height,
            init = function(s){
                surface = s;
                len = surface.length;
                width = surface.width;
                height = surface.height;
            },
            spriteProcessor = {
                path: function(sprite){

                    var attr = sprite.attr,
                        path = attr.path,
                        pathString = '',
                        props, p, pLen;

                    if(Ext.isArray(path[0])){
                        pLen = path.length;
                        for (p = 0; p < pLen; p++) {
                            pathString += path[p].join(' ');
                        }
                    }else if(Ext.isArray(path)){
                        pathString = path.join(' ');
                    }else{
                        pathString = path.replace(/,/g,' ');
                    }

                    props = toPropertyString({
                        d: pathString,
                        fill: attr.fill || 'none',
                        stroke: attr.stroke,
                        'fill-opacity': attr.opacity,
                        'stroke-width': attr['stroke-width'],
                        'stroke-opacity': attr['stroke-opacity'],
                        "z-index": attr.zIndex,
                        transform: sprite.matrix.toSvg()
                    });

                    return '<path ' + props + '/>';
                },
                text: function(sprite){

                    // TODO
                    // implement multi line support (@see Svg.js tuneText)

                    var attr = sprite.attr,
                        fontRegex = /(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)\s('*.*'*)/,
                        match = fontRegex.exec(attr.font),
                        size = (match && match[1]) || "12",
                        // default font family is Arial
                        family = (match && match[3]) || 'Arial',
                        text = attr.text,
                        factor = (Ext.isFF3_0 || Ext.isFF3_5) ? 2 : 4,
                        tspanString = '',
                        props;

                    sprite.getBBox();
                    tspanString += '<tspan x="' + (attr.x || '') + '" dy="';
                    tspanString += (size/factor)+'">';
                    tspanString += Ext.htmlEncode(text) + '</tspan>';

                    props = toPropertyString({
                            x: attr.x,
                            y: attr.y,
                            'font-size': size,
                            'font-family': family,
                            'font-weight': attr['font-weight'],
                            'text-anchor': attr['text-anchor'],
                            // if no fill property is set it will be black
                            fill: attr.fill || '#000',
                            'fill-opacity': attr.opacity,
                            transform: sprite.matrix.toSvg()
                    });

                    return '<text '+ props + '>' +  tspanString + '</text>';
                },
                rect: function(sprite){

                    var attr = sprite.attr,
                        props =  toPropertyString({
                            x: attr.x,
                            y: attr.y,
                            rx: attr.rx,
                            ry: attr.ry,
                            width: attr.width,
                            height: attr.height,
                            fill: attr.fill || 'none',
                            'fill-opacity': attr.opacity,
                            stroke: attr.stroke,
                            'stroke-opacity': attr['stroke-opacity'],
                            'stroke-width':attr['stroke-width'],
                            transform: sprite.matrix && sprite.matrix.toSvg()
                        });

                    return '<rect ' + props + '/>';
                },
                circle: function(sprite){

                    var attr = sprite.attr,
                        props = toPropertyString({
                            cx: attr.x,
                            cy: attr.y,
                            r: attr.radius,
                            fill: attr.translation.fill || attr.fill || 'none',
                            'fill-opacity': attr.opacity,
                            stroke: attr.stroke,
                            'stroke-opacity': attr['stroke-opacity'],
                            'stroke-width':attr['stroke-width'],
                            transform: sprite.matrix.toSvg()
                        });

                    return '<circle ' + props + ' />';
                },
                image: function(sprite){

                    var attr = sprite.attr,
                        props = toPropertyString({
                            x: attr.x - (attr.width/2 >> 0),
                            y: attr.y - (attr.height/2 >> 0),
                            width: attr.width,
                            height: attr.height,
                            'xlink:href': attr.src,
                            transform: sprite.matrix.toSvg()
                        });

                    return '<image ' + props + ' />';
                }
            },
            svgHeader = function(){
                var svg = '<?xml version="1.0" standalone="yes"?>';
                svg += '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';
                return svg;
            },
            svgContent = function(){
                var svg = '<svg width="'+width+'px" height="'+height+'px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">',
                    defs = '', item, itemsLen, items, gradient,
                    getSvgString, colorstops, stop,
                    coll, keys, colls, k, kLen, key, collI, i, j, stopsLen, sortedItems, za, zb;

                items = surface.items.items;
                itemsLen = items.length;

                getSvgString = function(node){

                    var childs = node.childNodes,
                        childLength = childs.length,
                        i = 0,
                        attrLength,
                        j,
                        svgString = '', child, attr, tagName, attrItem;

                        for(; i < childLength; i++){
                            child = childs[i];
                            attr = child.attributes;
                            tagName = child.tagName;

                            svgString += '<' +tagName;

                            for(j = 0, attrLength = attr.length; j < attrLength; j++){
                                attrItem = attr.item(j);
                                svgString += ' '+attrItem.name+'="'+attrItem.value+'"';
                            }

                            svgString += '>';

                            if(child.childNodes.length > 0){
                                svgString += getSvgString(child);
                            }

                            svgString += '</' + tagName + '>';

                        }
                    return svgString;
                };

                if(surface.getDefs){
                    defs = getSvgString(surface.getDefs());
                }else{
                    // IE
                    coll = surface.gradientsColl;
                    if (coll) {
                        keys  = coll.keys;
                        colls = coll.items;
                        k     = 0;
                        kLen  = keys.length;
                    }

                    for (; k < kLen; k++) {
                        key   = keys[k];
                        collI = colls[k];

                        gradient = surface.gradientsColl.getByKey(key);
                        defs += '<linearGradient id="' + key + '" x1="0" y1="0" x2="1" y2="1">';

                        var color = gradient.colors.replace(/rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g, 'rgb($1|$2|$3)');
                        color = color.replace(/rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,([\d\.]+)\)/g, 'rgba($1|$2|$3|$4)')
                        colorstops = color.split(',');
                        for(i=0, stopsLen = colorstops.length; i < stopsLen; i++){
                            stop = colorstops[i].split(' ');
                            color = Ext.draw.Color.fromString(stop[1].replace(/\|/g,','));
                            defs += '<stop offset="'+stop[0]+'" stop-color="' + color.toString() + '" stop-opacity="1"></stop>';
                        }
                        defs += '</linearGradient>';
                    }
                }

                svg += '<defs>' + defs + '</defs>';

                // thats the background rectangle
                svg += spriteProcessor.rect({
                    attr: {
                            width: '100%',
                            height: '100%',
                            fill: '#fff',
                            stroke: 'none',
                            opacity: '0'
                    }
                });

                // Sort the items (stable sort guaranteed)
                sortedItems = new Array(itemsLen);
                for(i = 0; i < itemsLen; i++){
                    sortedItems[i] = i;
                }
                sortedItems.sort(function (a, b) {
                    za = items[a].attr.zIndex || 0;
                    zb = items[b].attr.zIndex || 0;
                    if (za == zb) {
                        return a - b;
                    }
                    return za - zb;
                });

                for(i = 0; i < itemsLen; i++){
                    item = items[sortedItems[i]];
                    if(!item.attr.hidden){
                        svg += spriteProcessor[item.type](item);
                    }
                }

                svg += '</svg>';

                return svg;
            },
            toPropertyString = function(obj){
                var propString = '',
                    key;

                for(key in obj){

                    if(obj.hasOwnProperty(key) && obj[key] != null){
                        propString += key +'="'+ obj[key]+'" ';
                    }

                }

                return propString;
            };

            return {
                generate: function(config, surface){
                    init(surface);
                    return svgHeader() + svgContent();
                }
            };
        }())

    });