*
*/
-(function(R) {
- /**
- * Escapes string for XML interpolation
- * @param value string or number value to escape
- * @returns string escaped
- */
- function escapeXML(s) {
- if ( typeof s === 'number' ) return s.toString();
-
- var replace = {
+(function (R) {
+ /**
+ * Escapes string for XML interpolation
+ * @param value string or number value to escape
+ * @returns string escaped
+ */
+ function escapeXML(s) {
+ if (typeof s === 'number')
+ return s.toString();
+
+ var replace = {
'&': 'amp',
'<': 'lt',
'>': 'gt',
'\'': 'apos'
};
- for ( var entity in replace ) {
- s = s.replace(new RegExp(entity, 'g'), '&' + replace[entity] + ';');
- }
-
- return s;
- }
-
- /**
- * Generic map function
- * @param iterable the array or object to be mapped
- * @param callback the callback function(element, key)
- * @returns array
- */
- function map(iterable, callback) {
- var mapped = new Array;
-
- for ( var i in iterable ) {
- if ( iterable.hasOwnProperty(i) ) {
- var value = callback.call(this, iterable[i], i);
-
- if ( value !== null ) mapped.push(value);
- }
- }
-
- return mapped;
- }
-
- /**
- * Generic reduce function
- * @param iterable array or object to be reduced
- * @param callback the callback function(initial, element, i)
- * @param initial the initial value
- * @return the reduced value
- */
- function reduce(iterable, callback, initial) {
- for ( var i in iterable ) {
- if ( iterable.hasOwnProperty(i) ) {
- initial = callback.call(this, initial, iterable[i], i);
- }
- }
-
- return initial;
- }
-
- /**
- * Utility method for creating a tag
- * @param name the tag name, e.g., 'text'
- * @param attrs the attribute string, e.g., name1="val1" name2="val2"
- * or attribute map, e.g., { name1 : 'val1', name2 : 'val2' }
- * @param content the content string inside the tag
- * @returns string of the tag
- */
- function tag(name, attrs, matrix, content) {
- if ( typeof content === 'undefined' || content === null ) {
- content = '';
- }
-
- if ( typeof attrs === 'object' ) {
- attrs = map(attrs, function(element, name) {
- if ( name === 'transform') return;
-
- return name + '="' + escapeXML(element) + '"';
- }).join(' ');
- }
-
- return '<' + name + ( matrix ? ' transform="matrix(' + matrix.toString().replace(/^matrix\(|\)$/g, '') + ')" ' : ' ' ) + attrs + '>' +
- content +
- '</' + name + '>' + "\n";
- }
-
- /**
- * @return object the style object
- */
- function extractStyle(node) {
- return {
- font: {
- family: node.attrs.font.replace(/^.*?"(\w+)".*$/, '$1'),
- size: typeof node.attrs['font-size'] === 'undefined' ? null : node.attrs['font-size'],
- anchor : typeof node.attrs['text-anchor'] === 'undefined' ? null : node.attrs['text-anchor'],
- }
- };
- }
-
- /**
- * @param style object from style()
- * @return string
- */
- function styleToString(style) {
- // TODO figure out what is 'normal'
-
+ for (var entity in replace) {
+ s = s.replace(new RegExp(entity, 'g'), '&' + replace[entity] + ';');
+ }
+
+ return s;
+ }
+
+ /**
+ * Generic map function
+ * @param iterable the array or object to be mapped
+ * @param callback the callback function(element, key)
+ * @returns array
+ */
+ function map(iterable, callback) {
+ var mapped = new Array;
+
+ for (var i in iterable) {
+ if (iterable.hasOwnProperty(i)) {
+ var value = callback.call(this, iterable[i], i);
+
+ if (value !== null)
+ mapped.push(value);
+ }
+ }
+
+ return mapped;
+ }
+
+ /**
+ * Generic reduce function
+ * @param iterable array or object to be reduced
+ * @param callback the callback function(initial, element, i)
+ * @param initial the initial value
+ * @return the reduced value
+ */
+ function reduce(iterable, callback, initial) {
+ for (var i in iterable) {
+ if (iterable.hasOwnProperty(i)) {
+ initial = callback.call(this, initial, iterable[i], i);
+ }
+ }
+
+ return initial;
+ }
+
+ /**
+ * Utility method for creating a tag
+ * @param name the tag name, e.g., 'text'
+ * @param attrs the attribute string, e.g., name1="val1" name2="val2"
+ * or attribute map, e.g., { name1 : 'val1', name2 : 'val2' }
+ * @param content the content string inside the tag
+ * @returns string of the tag
+ */
+ function tag(name, attrs, matrix, content) {
+ if (typeof content === 'undefined' || content === null) {
+ content = '';
+ }
+
+ if (typeof attrs === 'object') {
+ attrs = map(attrs, function (element, name) {
+ if (name === 'transform')
+ return;
+
+ return name + '="' + escapeXML(element) + '"';
+ }).join(' ');
+ }
+
+ return '<' + name + (matrix ? ' transform="matrix(' + matrix.toString().replace(/^matrix\(|\)$/g, '') + ')" ' : ' ') + attrs + '>' +
+ content +
+ '</' + name + '>' + "\n";
+ }
+
+ /**
+ * @return object the style object
+ */
+ function extractStyle(node) {
+ return {
+ font: {
+ family: node.attrs.font.replace(/^.*?"(\w+)".*$/, '$1'),
+ size: typeof node.attrs['font-size'] === 'undefined' ? null : node.attrs['font-size'],
+ anchor: typeof node.attrs['text-anchor'] === 'undefined' ? null : node.attrs['text-anchor'],
+ }
+ };
+ }
+
+ /**
+ * @param style object from style()
+ * @return string
+ */
+ function styleToString(style) {
+ // TODO figure out what is 'normal'
+
var r = [
- 'font-family:' + style.font.family,
- 'font-weight:normal',
- 'font-style:normal',
- 'font-stretch:normal',
- 'font-variant:normal'
+ 'font-family:' + style.font.family,
+ 'font-weight:normal',
+ 'font-style:normal',
+ 'font-stretch:normal',
+ 'font-variant:normal'
];
- if (style.font.size !== null ) {
- r.push('font-size: ' + style.font.size + 'px')
+ if (style.font.size !== null) {
+ r.push('font-size: ' + style.font.size + 'px')
}
-
+
return r.join(';')
-
- }
-
- /**
- * Computes tspan dy using font size. This formula was empircally determined
- * using a best-fit line. Works well in both VML and SVG browsers.
- * @param fontSize number
- * @return number
- */
- function computeTSpanDy(fontSize, line, lines) {
- if ( fontSize === null ) fontSize = 10;
-
- //return fontSize * 4.5 / 13
- return fontSize * 4.5 / 13 * ( line - .2 - lines / 2 ) * 3.5;
- }
-
- var serializer = {
- 'text': function(node) {
- style = extractStyle(node);
+
+ }
+
+ /**
+ * Computes tspan dy using font size. This formula was empircally determined
+ * using a best-fit line. Works well in both VML and SVG browsers.
+ * @param fontSize number
+ * @return number
+ */
+ function computeTSpanDy(fontSize, line, lines) {
+ if (fontSize === null)
+ fontSize = 10;
+
+ //return fontSize * 4.5 / 13
+ return fontSize * 4.5 / 13 * (line - .2 - lines / 2) * 3.5;
+ }
+
+ var serializer = {
+ 'text': function (node) {
+ style = extractStyle(node);
Roo.log(style);
- var tags = new Array;
+ var tags = new Array;
- map(node.attrs['text'].split('\n'), function(text, iterable, line) {
+ map(node.attrs['text'].split('\n'), function (text, iterable, line) {
line = line || 0;
- tags.push(tag(
- 'text',
- reduce(
- node.attrs,
- function(initial, value, name) {
- if ( name !== 'text' && name !== 'w' && name !== 'h' ) {
- if ( name === 'font-size') value = value + 'px';
-
- initial[name] = escapeXML(value.toString());
- }
-
- return initial;
- },
- {
- style: 'text-anchor: ' + (style.font.anchor ? (style.font.anchor +';' ): 'middle;') +
- styleToString(style) + ';'
- }
- ),
- node.matrix,
- tag('tspan',
- {
- dy: computeTSpanDy(style.font.size, line + 1, node.attrs['text'].split('\n').length)
+ tags.push(tag(
+ 'text',
+ reduce(
+ node.attrs,
+ function (initial, value, name) {
+ if (name !== 'text' && name !== 'w' && name !== 'h') {
+ if (name === 'font-size')
+ value = value + 'px';
+
+ initial[name] = escapeXML(value.toString());
+ }
+
+ return initial;
+ },
+ {
+ style: 'text-anchor: ' + (style.font.anchor ? (style.font.anchor + ';') : 'middle;') +
+ styleToString(style) + ';'
+ }
+ ),
+ node.matrix,
+ tag('tspan',
+ {
+ dy: computeTSpanDy(style.font.size, line + 1, node.attrs['text'].split('\n').length)
+ },
+ null,
+ escapeXML(text)
+ )
+ ));
+ });
+
+ return tags;
+ },
+ 'path': function (node) {
+ var initial = (node.matrix.a === 1 && node.matrix.d === 1) ? {} : {'transform': node.matrix.toString()};
+
+
+
+ return tag(
+ 'path',
+ reduce(
+ node.attrs,
+ function (initial, value, name) {
+ if (name === 'path') {
+ name = 'd';
+ }
+
+ initial[name] = (typeof (value) == 'undefined') ? '' : value.toString();
+
+ return initial;
},
- null,
- escapeXML(text)
- )
- ));
- });
-
- return tags;
- },
- 'path' : function(node) {
- var initial = ( node.matrix.a === 1 && node.matrix.d === 1 ) ? {} : { 'transform' : node.matrix.toString() };
-
-
-
- return tag(
- 'path',
- reduce(
- node.attrs,
- function(initial, value, name) {
- if ( name === 'path' ) {
- name = 'd';
- }
-
- initial[name] = (typeof(value) == 'undefined') ? '' : value.toString();
-
- return initial;
- },
- {
- style: 'fill:' + Raphael.color(node.attrs.fill).hex + ';'
- }
- ),
- node.matrix
- );
- }
- // Other serializers should go here
- };
-
- R.fn.toSVG = function() {
- var
- paper = this,
- restore = { svg: R.svg, vml: R.vml },
- svg = '<svg style="overflow: hidden; position: relative;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="' + paper.width + '" version="1.1" height="' + paper.height + '">'
- ;
-
- R.svg = true;
- R.vml = false;
-
- for ( var node = paper.bottom; node != null; node = node.next ) {
- if ( node.node.style.display === 'none' ) continue;
-
- var attrs = '';
-
- // Use serializer
- if ( typeof serializer[node.type] === 'function' ) {
- svg += serializer[node.type](node);
-
- continue;
- }
-
- switch ( node.type ) {
- case 'image':
- attrs += ' preserveAspectRatio="none"';
- break;
- }
-
- for ( i in node.attrs ) {
- var name = i;
+ {
+ style: 'fill:' + Raphael.color(node.attrs.fill).hex + ';'
+ }
+ ),
+ node.matrix
+ );
+ }
+ // Other serializers should go here
+ };
+
+ R.fn.toSVG = function () {
+ var
+ paper = this,
+ restore = {svg: R.svg, vml: R.vml},
+ svg = '<svg style="overflow: hidden; position: relative;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="' + paper.width + '" version="1.1" height="' + paper.height + '">';
+
+ R.svg = true;
+ R.vml = false;
+
+ for (var node = paper.bottom; node != null; node = node.next) {
+ if (node.node.style.display === 'none')
+ continue;
+
+ var attrs = '';
+
+ // Use serializer
+ if (typeof serializer[node.type] === 'function') {
+ svg += serializer[node.type](node);
+
+ continue;
+ }
+
+ switch (node.type) {
+ case 'image':
+ attrs += ' preserveAspectRatio="none"';
+ break;
+ }
+
+ for (i in node.attrs) {
+ var name = i;
var val = node.attrs[i].toString();
- switch ( i ) {
- case 'src':
- name = 'xlink:href';
-
- break;
- case 'transform':
- name = '';
- break;
-
+ switch (i) {
+ case 'src':
+ name = 'xlink:href';
+
+ break;
+ case 'transform':
+ name = '';
+ break;
+
case 'stroke':
case 'fill':
val = Raphael.getRGB(val).hex;
break;
- }
+ }
- if ( name ) {
- attrs += ' ' + name + '="' + escapeXML(val) + '"';
- }
- }
+ if (name) {
+ attrs += ' ' + name + '="' + escapeXML(val) + '"';
+ }
+ }
- svg += '<' + node.type + ' transform="matrix(' + node.matrix.toString().replace(/^matrix\(|\)$/g, '') + ')"' + attrs + '></' + node.type + '>';
- }
+ svg += '<' + node.type + ' transform="matrix(' + node.matrix.toString().replace(/^matrix\(|\)$/g, '') + ')"' + attrs + '></' + node.type + '>';
+ }
- svg += '</svg>';
+ svg += '</svg>';
- R.svg = restore.svg;
- R.vml = restore.vml;
+ R.svg = restore.svg;
+ R.vml = restore.vml;
- return svg;
- };
+ return svg;
+ };
})(window.Raphael);
\ No newline at end of file