<!DOCTYPE html>
|
<html>
|
<head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<title>The source code</title>
|
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
|
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
|
<style type="text/css">
|
.highlight { display: block; background-color: #ddd; }
|
</style>
|
<script type="text/javascript">
|
function highlight() {
|
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
|
}
|
</script>
|
</head>
|
<body onload="prettyPrint(); highlight();">
|
<pre class="prettyprint lang-js"><span id='Ext-draw-engine-SvgExporter'>/**
|
</span> * A utility class for exporting a {@link Ext.draw.Surface Surface} to a string
|
* that may be saved or used for processing on the server.
|
*
|
* @singleton
|
*/
|
Ext.define('Ext.draw.engine.SvgExporter', function(){
|
var commaRe = /,/g,
|
fontRegex = /(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)\s('*.*'*)/,
|
rgbColorRe = /rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g,
|
rgbaColorRe = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,([\d\.]+)\)/g,
|
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(commaRe,' ');
|
}
|
|
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,
|
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(rgbColorRe, 'rgb($1|$2|$3)');
|
color = color.replace(rgbaColorRe, '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 {
|
singleton: true,
|
|
<span id='Ext-draw-engine-SvgExporter-method-generate'> /**
|
</span> * Exports the passed surface to a SVG string representation
|
* @param {Ext.draw.Surface} surface The surface to export
|
* @param {Object} [config] Any configuration for the export. Currently this is
|
* unused but may provide more options in the future
|
* @return {String} The SVG as a string
|
*/
|
generate: function(surface, config){
|
config = config || {};
|
init(surface);
|
return svgHeader() + svgContent();
|
}
|
};
|
});</pre>
|
</body>
|
</html>
|