Index: trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java	(revision 4327)
+++ trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java	(revision 4328)
@@ -106,5 +106,5 @@
     }
 
-    /*boolean debug = false;*/
+    /*boolean debug = true;*/
 
     protected MemoryTileCache tileCache;
@@ -311,5 +311,9 @@
         double factor = getScaleFactor(1);
         double result = Math.log(factor)/Math.log(2)/2+1;
-        int intResult = (int)Math.round(result);
+        // In general, smaller zoom levels are more readable.  We prefer big,
+        // block, pixelated (but readable) map text to small, smeared,
+        // unreadable underzoomed text.  So, use .floor() instead of rounding
+        // to skew things a bit toward the lower zooms.
+        int intResult = (int)Math.floor(result);
         if (intResult > getMaxZoomLvl())
             return getMaxZoomLvl();
@@ -822,5 +826,10 @@
         }
         List<Tile> missedTiles = new LinkedList<Tile>();
-        for (Tile tile : ts.allTiles()) {
+        // The callers of this code *require* that we return any tiles
+        // that we do not draw in missedTiles.  ts.allTiles() by default
+        // will only return already-existing tiles.  However, we need
+        // to return *all* tiles to the callers, so force creation here.
+        boolean forceTileCreation = true;
+        for (Tile tile : ts.allTiles(forceTileCreation)) {
             Image img = getLoadedTileImage(tile);
             if (img == null || tile.hasError()) {
@@ -1028,4 +1037,13 @@
             return ret;
         }
+        private List<Tile> allLoadedTiles()
+        {
+            List<Tile> ret = new ArrayList<Tile>();
+            for (Tile t : this.allTiles()) {
+                if (t.isLoaded())
+                    ret.add(t);
+            }
+            return ret;
+        }
 
         void loadAllTiles(boolean force)
@@ -1130,5 +1148,5 @@
         if (autoZoom) {
             double pixelScaling = getScaleFactor(zoom);
-            if (pixelScaling > 3 || pixelScaling < 0.45) {
+            if (pixelScaling > 3 || pixelScaling < 0.7) {
                 zoom = getBestZoom();
             }
@@ -1192,11 +1210,9 @@
         int otherZooms[] = { -1, 1, -2, 2, -3, -4, -5};
         for (int zoomOffset : otherZooms) {
-            if (!autoZoom) {
+            if (!autoZoom)
                 break;
-            }
-            if (!autoLoad) {
-                break;
-            }
             int newzoom = displayZoomLevel + zoomOffset;
+            if (newzoom < MIN_ZOOM)
+                continue;
             if (missedTiles.size() <= 0) {
                 break;
@@ -1213,4 +1229,10 @@
                 LatLon botRight2 = tileLatLon(t2);
                 TileSet ts2 = new TileSet(topLeft2, botRight2, newzoom);
+                // Instantiating large TileSets is expensive.  If there
+                // are no loaded tiles, don't bother even trying.
+                if (ts2.allLoadedTiles().size() == 0) {
+                    newlyMissedTiles.add(missed);
+                    continue;
+                }
                 if (ts2.tooLarge()) {
                     continue;
