Index: lib/OpenLayers/Renderer/SVG.js
===================================================================
--- lib/OpenLayers/Renderer/SVG.js	(revision 3070)
+++ lib/OpenLayers/Renderer/SVG.js	(working copy)
@@ -13,7 +13,17 @@
 
     /** @type String */
     xmlns: "http://www.w3.org/2000/svg",
+
+    // Firefox has a limitation where values larger or smaller than about
+    // this.localResolution in an SVG document lock the browser up. This works around it.
+    /** @type Integer */
+    maxPixel: this.localResolution,
     
+
+    /** @type Float 
+        @private */
+    localResolution: null,
+
     /**
      * @constructor
      * 
@@ -54,8 +64,33 @@
         
         var resolution = this.getResolution();
         
-        var extentString = extent.left / resolution + " " + -extent.top / resolution + " " + 
+
+        // If the resolution has changed, start over changing the corner, because
+        // the features will redraw.
+        if (!this.localResolution || resolution != this.localResolution) {
+            this.left = -extent.left / resolution;
+            this.top = extent.top / resolution;
+        }
+
+        
+        var left = 0;
+        var top = 0;
+
+        // If the resolution has not changed, we already have features, and we need
+        // to adjust the viewbox to fit them.
+        if (this.localResolution && resolution == this.localResolution) {
+            left = (this.left) - (-extent.left / resolution);
+            top  = (this.top) - (extent.top / resolution);
+        }    
+        
+        // Store resolution for use later.
+        this.localResolution = resolution;
+        
+        // Set the viewbox -- the left/top will be pixels-dragged-since-res change,
+        // the width/height will be pixels.
+        var extentString = left + " " + top + " " + 
                              extent.getWidth() / resolution + " " + extent.getHeight() / resolution;
+        //var extentString = extent.left / resolution + " " + -extent.top / resolution + " " + 
         this.rendererRoot.setAttributeNS(null, "viewBox", extentString);
     },
 
@@ -236,9 +271,22 @@
      */
     drawCircle: function(node, geometry, radius) {
         var resolution = this.getResolution();
-        node.setAttributeNS(null, "cx", geometry.x / resolution);
-        node.setAttributeNS(null, "cy", geometry.y / resolution);
-        node.setAttributeNS(null, "r", radius);
+        var x = (geometry.x / resolution + this.left);
+        var y = (geometry.y / resolution - this.top);
+        var draw = true;
+        if (x < -this.maxPixel || x > this.maxPixel) { draw = false; }
+        if (y < -this.maxPixel || y > this.maxPixel) { draw = false; }
+
+        if (draw) { 
+            node.setAttributeNS(null, "cx", x);
+            node.setAttributeNS(null, "cy", y);
+            node.setAttributeNS(null, "r", radius);
+        } else {
+            node.setAttributeNS(null, "cx", "");
+            node.setAttributeNS(null, "cy", "");
+            node.setAttributeNS(null, "r", 0);
+        }    
+            
     },
     
     /** 
@@ -266,17 +314,26 @@
      */
     drawPolygon: function(node, geometry) {
         var d = "";
+        var draw = true;
         for (var j = 0; j < geometry.components.length; j++) {
             var linearRing = geometry.components[j];
             d += " M";
             for (var i = 0; i < linearRing.components.length; i++) {
-                d += " " + this.getShortString(linearRing.components[i]);
+                var component = this.getShortString(linearRing.components[i])
+                if (component) {
+                    d += " " + component;
+                } else {
+                    draw = false;
+                }    
             }
         }
         d += " z";
-        
-        node.setAttributeNS(null, "d", d);
-        node.setAttributeNS(null, "fill-rule", "evenodd");
+        if (draw) {
+            node.setAttributeNS(null, "d", d);
+            node.setAttributeNS(null, "fill-rule", "evenodd");
+        } else {
+            node.setAttributeNS(null, "d", "");
+        }    
     },
     
     /** 
@@ -285,10 +342,24 @@
      * @private
      */
     drawRectangle: function(node, geometry) {
-        node.setAttributeNS(null, "x", geometry.x / resolution);
-        node.setAttributeNS(null, "y", geometry.y / resolution);
-        node.setAttributeNS(null, "width", geometry.width);
-        node.setAttributeNS(null, "height", geometry.height);
+        // This needs to be reworked 
+        var x = (geometry.x / resolution + this.left);
+        var y = (geometry.y / resolution - this.top);
+        var draw = true;
+        if (x < -this.maxPixel || x > this.maxPixel) { draw = false; }
+        if (y < -this.maxPixel || y > this.maxPixel) { draw = false; }
+        if (draw) {
+            node.setAttributeNS(null, "x", x);
+            node.setAttributeNS(null, "y", y);
+            node.setAttributeNS(null, "width", geometry.width);
+            node.setAttributeNS(null, "height", geometry.height);
+        } else {
+            node.setAttributeNS(null, "x", "");
+            node.setAttributeNS(null, "y", "");
+            node.setAttributeNS(null, "width", 0);
+            node.setAttributeNS(null, "height", 0);
+        }    
+
     },
     
     
@@ -299,16 +370,27 @@
      */
     drawCurve: function(node, geometry) {
         var d = null;
+        var draw = true;
         for (var i = 0; i < geometry.components.length; i++) {
             if ((i%3) == 0 && (i/3) == 0) {
-                d = "M " + this.getShortString(geometry.components[i]);
+                var component = this.getShortString(geometry.components[i]);
+                if (!component) { draw = false; }
+                d = "M " + component;
             } else if ((i%3) == 1) {
-                d += " C " + this.getShortString(geometry.components[i]);
+                var component = this.getShortString(geometry.components[i]);
+                if (!component) { draw = false; }
+                d += " C " + component;
             } else {
-                d += " " + this.getShortString(geometry.components[i]);
+                var component = this.getShortString(geometry.components[i]);
+                if (!component) { draw = false; }
+                d += " " + component;
             }
         }
-        node.setAttributeNS(null, "d", d);
+        if (draw) {
+            node.setAttributeNS(null, "d", d);
+        } else {
+            node.setAttributeNS(null, "d", "");
+        }    
     },
     
     /** 
@@ -320,17 +402,28 @@
 
         // create the svg path string representation
         var d = null;
+        var draw = true;
         for (var i = 0; i < geometry.components.length; i++) {
             if ((i%3) == 0 && (i/3) == 0) {
-                d = "M " + this.getShortString(geometry.components[i]);
+                var component = this.getShortString(geometry.components[i]);
+                if (!component) { draw = false; }
+                d = "M " + component;
             } else if ((i%3) == 1) {
-                d += " C " + this.getShortString(geometry.components[i]);
+                var component = this.getShortString(geometry.components[i]);
+                if (!component) { draw = false; }
+                d += " C " + component;
             } else {
-                d += " " + this.getShortString(geometry.components[i]);
+                var component = this.getShortString(geometry.components[i]);
+                if (!component) { draw = false; }
+                d += " " + component;
             }
         }
         d += " Z";
-        node.setAttributeNS(null, "d", d);
+        if (draw) {
+            node.setAttributeNS(null, "d", d);
+        } else {
+            node.setAttributeNS(null, "d", "");
+        }    
     },
 
     /** 
@@ -340,7 +433,9 @@
     getComponentsString: function(components) {
         var strings = [];
         for(var i = 0; i < components.length; i++) {
-            strings.push(this.getShortString(components[i]));
+            var component = this.getShortString(components[i]);
+            if (!component) { return false; }
+            strings.push(component);
         }
         return strings.join(",");
     },
@@ -352,7 +447,12 @@
      */
     getShortString: function(point) {
         var resolution = this.getResolution();
-        return point.x / resolution + "," + point.y / resolution;  
+        var x = (point.x / resolution + this.left);
+        var y = (point.y / resolution - this.top);
+        if (x < -this.maxPixel || x > this.maxPixel) { return false; }
+        if (y < -this.maxPixel || y > this.maxPixel) { return false; }
+        var string =  x + "," + y;  
+        return string;
         
     },
     
