diff --git a/node.js/index.js b/node.js/index.js
index ee8ffc97..9cb6035d 100644
--- a/node.js/index.js
+++ b/node.js/index.js
@@ -21,6 +21,7 @@ __dirname = path.resolve(__dirname, '../src/');
 var context = vm.createContext({
 	options: {
 		server: true,
+		svg: true,
 		parser: 'acorn',
 		version: 'dev'
 	},
diff --git a/src/basic/Matrix.js b/src/basic/Matrix.js
index 518b0643..e819a53c 100644
--- a/src/basic/Matrix.js
+++ b/src/basic/Matrix.js
@@ -261,7 +261,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
 	 * @return {String} A string representation of this transform.
 	 */
 	toString: function() {
-		var format = Base.formatFloat;
+		var format = Format.number;
 		return '[[' + [format(this._a), format(this._b),
 					format(this._tx)].join(', ') + '], ['
 				+ [format(this._c), format(this._d),
diff --git a/src/basic/Point.js b/src/basic/Point.js
index c045cf34..15e6f6d0 100644
--- a/src/basic/Point.js
+++ b/src/basic/Point.js
@@ -165,8 +165,8 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 	},
 
 	_serialize: function(options) {
-		var format = Base.formatFloat;
-		// For speed reasons, we directly call formatFloat() here with
+		var format = Format.number;
+		// For speed reasons, we directly call Format.number() here with
 		// precision, instead of converting array through Base.serialize() which
 		// makes a copy.
 		return [format(this.x, options.precision),
@@ -214,7 +214,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 	 * @return {String} A string representation of the point.
 	 */
 	toString: function() {
-		var format = Base.formatFloat;
+		var format = Format.number;
 		return '{ x: ' + format(this.x) + ', y: ' + format(this.y) + ' }';
 	},
 
diff --git a/src/basic/Rectangle.js b/src/basic/Rectangle.js
index d1e1256d..52ea6cca 100644
--- a/src/basic/Rectangle.js
+++ b/src/basic/Rectangle.js
@@ -419,7 +419,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
 	 * @return {String} A string representation of this rectangle.
 	 */
 	toString: function() {
-		var format = Base.formatFloat;
+		var format = Format.number;
 		return '{ x: ' + format(this.x)
 				+ ', y: ' + format(this.y)
 				+ ', width: ' + format(this.width)
diff --git a/src/basic/Size.js b/src/basic/Size.js
index 2d47ca3e..addc7515 100644
--- a/src/basic/Size.js
+++ b/src/basic/Size.js
@@ -125,7 +125,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
 	 * @return {String} A string representation of the size.
 	 */
 	toString: function() {
-		var format = Base.formatFloat;
+		var format = Format.number;
 		return '{ width: ' + format(this.width)
 				+ ', height: ' + format(this.height) + ' }';
 	},
diff --git a/src/color/Color.js b/src/color/Color.js
index fffad69e..e5e8b964 100644
--- a/src/color/Color.js
+++ b/src/color/Color.js
@@ -283,7 +283,7 @@ var Color = this.Color = Base.extend(new function() {
 				var component = this._components[i],
 					value = this['_' + component];
 				if (component !== 'alpha' || value != null && value < 1)
-					res.push(Base.formatFloat(value, options.precision));
+					res.push(Format.number(value, options.precision));
 			}
 			return res;
 		},
@@ -471,7 +471,7 @@ var Color = this.Color = Base.extend(new function() {
 	 */
 	toString: function() {
 		var parts = [],
-			format = Base.formatFloat;
+			format = Format.number;
 		for (var i = 0, l = this._components.length; i < l; i++) {
 			var component = this._components[i],
 				value = this['_' + component];
diff --git a/src/core/Base.js b/src/core/Base.js
index bb1be6a5..252c78e7 100644
--- a/src/core/Base.js
+++ b/src/core/Base.js
@@ -40,7 +40,7 @@ this.Base = Base.inject(/** @lends Base# */{
 			if (!/^_/.test(key)) {
 				var type = typeof value;
 				this.push(key + ': ' + (type === 'number'
-						? Base.formatFloat(value)
+						? Format.number(value)
 						: type === 'string' ? "'" + value + "'" : value));
 			}
 		}, []).join(', ') + ' }';
@@ -324,7 +324,7 @@ this.Base = Base.inject(/** @lends Base# */{
 						res[i] = Base.serialize(obj[i], options, compact,
 								dictionary);
 			} else if (typeof obj === 'number') {
-				res = Base.formatFloat(obj, options.precision);
+				res = Format.number(obj, options.precision);
 			} else {
 				res = obj;
 			}
@@ -458,18 +458,6 @@ this.Base = Base.inject(/** @lends Base# */{
 		 */
 		hyphenate: function(str) {
 			return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
-		},
-
-		/**
-		 * Utility function for rendering numbers to strings at a precision of
-		 * up to the amount of fractional digits.
-		 *
-		 * @param {Number} num the number to be converted to a string
-		 * @param {Number} [precision=5] the amount of fractional digits.
-		 */
-		formatFloat: function(num, precision) {
-			precision = precision ? Math.pow(10, precision) : 100000;
-			return Math.round(num * precision) / precision;
 		}
 	}
 });
diff --git a/src/load.js b/src/load.js
index ca24f1fc..45d819be 100644
--- a/src/load.js
+++ b/src/load.js
@@ -18,6 +18,7 @@
 var options = {
 	browser: true,
 	stats: true,
+	svg: true,
 	version: 'dev',
 	parser: 'acorn',
 	debug: false
diff --git a/src/paper.js b/src/paper.js
index 1d0b5e6b..26ba81b5 100644
--- a/src/paper.js
+++ b/src/paper.js
@@ -81,10 +81,6 @@ var paper = new function() {
 /*#*/ include('text/TextItem.js');
 /*#*/ include('text/PointText.js');
 
-/*#*/ include('svg/SvgStyles.js');
-/*#*/ include('svg/SvgExport.js');
-/*#*/ include('svg/SvgImport.js');
-
 /*#*/ include('style/Style.js');
 /*#*/ include('style/PathStyle.js');
 /*#*/ include('style/ParagraphStyle.js');
@@ -116,6 +112,7 @@ var paper = new function() {
 /*#*/ include('tool/Tool.js');
 /*#*/ } // options.browser
 
+/*#*/ include('util/Format.js');
 /*#*/ include('util/CanvasProvider.js');
 /*#*/ include('util/Numerical.js');
 /*#*/ include('util/BlendMode.js');
@@ -123,6 +120,12 @@ var paper = new function() {
 /*#*/ include('util/ProxyContext.js');
 /*#*/ } // options.browser
 
+/*#*/ if (options.svg) {
+/*#*/ include('svg/SvgStyles.js');
+/*#*/ include('svg/SvgExport.js');
+/*#*/ include('svg/SvgImport.js');
+/*#*/ } // options.svg
+
 /*#*/ include('core/PaperScript.js');
 
 /*#*/ if (options.browser) {
diff --git a/src/path/CurveLocation.js b/src/path/CurveLocation.js
index becd1ead..1e722244 100644
--- a/src/path/CurveLocation.js
+++ b/src/path/CurveLocation.js
@@ -231,9 +231,9 @@ var CurveLocation = this.CurveLocation = Base.extend(/** @lends CurveLocation# *
 			parts.push('index: ' + index);
 		var parameter = this.getParameter();
 		if (parameter != null)
-			parts.push('parameter: ' + Base.formatFloat(parameter));
+			parts.push('parameter: ' + Format.number(parameter));
 		if (this._distance != null)
-			parts.push('distance: ' + Base.formatFloat(this._distance));
+			parts.push('distance: ' + Format.number(this._distance));
 		return '{ ' + parts.join(', ') + ' }';
 	}
 });
diff --git a/src/svg/SvgExport.js b/src/svg/SvgExport.js
index 63da2de5..858947ef 100644
--- a/src/svg/SvgExport.js
+++ b/src/svg/SvgExport.js
@@ -15,27 +15,18 @@
  * Paper.js DOM to a Paper.js DOM.
  */
 new function() {
-	// Shortcut to Base.formatFloat
-	var formatFloat = Base.formatFloat,
+	// Shortcut to Format.number
+	var format = Format.number,
 		namespaces = {
 			href: 'http://www.w3.org/1999/xlink'
 		};
 
-	function formatPoint(point) {
-		return formatFloat(point.x) + ',' + formatFloat(point.y);
-	}
-
-	function formatRectangle(rect) {
-		return formatFloat(rect.x) + ',' + formatFloat(rect.y)
-			+ ',' + formatFloat(rect.width) + ',' + formatFloat(rect.height);
-	}
-
 	function setAttributes(node, attrs) {
 		for (var key in attrs) {
 			var val = attrs[key],
 				namespace = namespaces[key];
 			if (typeof val === 'number')
-				val = formatFloat(val);
+				val = format(val);
 			if (namespace) {
 				node.setAttributeNS(namespace, key, val);
 			} else {
@@ -81,11 +72,11 @@ new function() {
 				angle = decomposed.rotation,
 				scale = decomposed.scaling;
 			if (trans && !trans.isZero())
-				parts.push('translate(' + formatPoint(trans) + ')');
+				parts.push('translate(' + Format.point(trans) + ')');
 			if (!Numerical.isZero(scale.x - 1) || !Numerical.isZero(scale.y - 1))
-				parts.push('scale(' + formatPoint(scale) +')');
+				parts.push('scale(' + Format.point(scale) +')');
 			if (angle)
-				parts.push('rotate(' + formatFloat(angle) + ')');
+				parts.push('rotate(' + format(angle) + ')');
 			attrs.transform = parts.join(' ');
 		} else {
 			attrs.transform = 'matrix(' + matrix.getValues().join(',') + ')';
@@ -269,7 +260,7 @@ new function() {
 		case 'polygon':
 			var parts = [];
 			for(i = 0, l = segments.length; i < l; i++)
-				parts.push(formatPoint(segments[i]._point));
+				parts.push(Format.point(segments[i]._point));
 			attrs = {
 				points: parts.join(' ')
 			};
@@ -342,8 +333,8 @@ new function() {
 			break;
 		}
 		if (angle) {
-			attrs.transform = 'rotate(' + formatFloat(angle) + ','
-					+ formatPoint(center) + ')';
+			attrs.transform = 'rotate(' + format(angle) + ','
+					+ Format.point(center) + ')';
 			// Tell applyStyle() that to transform the gradient the other way
 			item._gradientMatrix = new Matrix().rotate(-angle, center);
 		}
@@ -355,7 +346,7 @@ new function() {
 			children = item._children,
 			paths = [];
 		for (var i = 0, l = children.length; i < l; i++)
-			paths.push(getPath(children[i]));
+			paths.push(children[i].getPathData());
 		attrs.d = paths.join(' ');
 		return createElement('path', attrs);
 	}
@@ -368,7 +359,7 @@ new function() {
 			bounds = definition.getBounds();
 		if (!symbolNode) {
 			symbolNode = createElement('symbol', {
-				viewBox: formatRectangle(bounds)
+				viewBox: Format.rectangle(bounds)
 			});
 			symbolNode.appendChild(exportSvg(definition));
 			setDefinition(symbol, symbolNode);
@@ -376,8 +367,8 @@ new function() {
 		attrs.href = '#' + symbolNode.id;
 		attrs.x += bounds.x;
 		attrs.y += bounds.y;
-		attrs.width = formatFloat(bounds.width);
-		attrs.height = formatFloat(bounds.height);
+		attrs.width = format(bounds.width);
+		attrs.height = format(bounds.height);
 		return createElement('use', attrs);
 	}
 
@@ -472,7 +463,7 @@ new function() {
 						: entry.type === 'array'
 							? value.join(',')
 							: entry.type === 'number'
-								? formatFloat(value)
+								? format(value)
 								: value;
 			}
 		});
diff --git a/src/util/Format.js b/src/util/Format.js
new file mode 100644
index 00000000..326351a7
--- /dev/null
+++ b/src/util/Format.js
@@ -0,0 +1,39 @@
+var Format = new function() {
+	// Cache for precision values, linking prec -> Math.pow(10, prec)
+	var precisions = {};
+
+	function number(val, prec) {
+		prec = prec
+				? precisions[prec] || (precisions[prec] = Math.pow(10, prec))
+				: 100000; // Default is 5
+		return Math.round(val * prec) / prec;
+	}
+
+	function point(val, prec, separator) {
+		return number(val.x, prec) + (separator || ',') + number(val.y, prec);
+	}
+
+	function size(val, prec, separator) {
+		return number(val.width, prec) + (separator || ',')
+				+ number(val.height, prec);
+	}
+
+	function rectangle(val, prec, separator) {
+		return point(val, prec, separator) + (separator || ',')
+				+ size(val, prec, separator);
+	}
+
+	return {
+		/**
+		 * Utility function for rendering numbers as strings at a precision of
+		 * up to the amount of fractional digits.
+		 *
+		 * @param {Number} num the number to be converted to a string
+		 * @param {Number} [precision=5] the amount of fractional digits.
+		 */
+		number: number,
+		point: point,
+		size: size,
+		rectangle: rectangle
+	};
+};