Index: trunk/src/org/openstreetmap/josm/data/imagery/TemplatedWMSTileSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/imagery/TemplatedWMSTileSource.java	(revision 9175)
+++ trunk/src/org/openstreetmap/josm/data/imagery/TemplatedWMSTileSource.java	(revision 9176)
@@ -22,4 +22,5 @@
 import org.openstreetmap.gui.jmapviewer.tilesources.TMSTileSource;
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.ProjectionBounds;
 import org.openstreetmap.josm.data.coor.EastNorth;
@@ -38,5 +39,7 @@
     private final Map<String, String> headers = new ConcurrentHashMap<>();
     private final Set<String> serverProjections;
-    private EastNorth topLeftCorner;
+    private EastNorth anchorPosition;
+    private int[] tileXMin;
+    private int[] tileYMin;
     private int[] tileXMax;
     private int[] tileYMax;
@@ -89,4 +92,11 @@
     }
 
+    private void initAnchorPosition(Projection proj) {
+        Bounds worldBounds = proj.getWorldBoundsLatLon();
+        EastNorth min = proj.latlon2eastNorth(worldBounds.getMin());
+        EastNorth max = proj.latlon2eastNorth(worldBounds.getMax());
+        this.anchorPosition = new EastNorth(min.east(), max.north());
+    }
+
     /**
      * Initializes class with projection in JOSM. This call is needed every time projection changes.
@@ -94,13 +104,14 @@
      */
     public void initProjection(Projection proj) {
+        initAnchorPosition(proj);
         ProjectionBounds worldBounds = proj.getWorldBoundsBoxEastNorth();
-        EastNorth min = worldBounds.getMin();
-        EastNorth max = worldBounds.getMax();
-        this.topLeftCorner = new EastNorth(min.east(), max.north());
-
+
+        EastNorth topLeft = new EastNorth(worldBounds.getMin().east(), worldBounds.getMax().north());
         EastNorth bottomRight = new EastNorth(worldBounds.getMax().east(), worldBounds.getMin().north());
 
         // use 256 as "tile size" to keep the scale in line with default tiles in Mercator projection
         double crsScale = 256 * 0.28e-03 / proj.getMetersPerUnit();
+        tileXMin = new int[getMaxZoom() + 1];
+        tileYMin = new int[getMaxZoom() + 1];
         tileXMax = new int[getMaxZoom() + 1];
         tileYMax = new int[getMaxZoom() + 1];
@@ -111,4 +122,7 @@
             // this makes the zoom levels "glued" to standard TMS zoom levels
             degreesPerTile[zoom] = (SCALE_DENOMINATOR_ZOOM_LEVEL_1 / Math.pow(2, zoom - 1)) * crsScale;
+            TileXY minTileIndex = eastNorthToTileXY(topLeft, zoom);
+            tileXMin[zoom] = minTileIndex.getXIndex();
+            tileYMin[zoom] = minTileIndex.getYIndex();
             TileXY maxTileIndex = eastNorthToTileXY(bottomRight, zoom);
             tileXMax[zoom] = maxTileIndex.getXIndex();
@@ -247,6 +261,6 @@
         double scale = getDegreesPerTile(zoom);
         return new TileXY(
-                (enPoint.east() - topLeftCorner.east()) / scale,
-                (topLeftCorner.north() - enPoint.north()) / scale
+                (enPoint.east() - anchorPosition.east()) / scale,
+                (anchorPosition.north() - enPoint.north()) / scale
                 );
     }
@@ -264,5 +278,5 @@
     @Override
     public int getTileXMin(int zoom) {
-        return 0;
+        return tileXMin[zoom];
     }
 
@@ -274,5 +288,5 @@
     @Override
     public int getTileYMin(int zoom) {
-        return 0;
+        return tileYMin[zoom];
     }
 
@@ -282,6 +296,6 @@
         EastNorth point = Main.getProjection().latlon2eastNorth(new LatLon(lat, lon));
         return new Point(
-                    (int) Math.round((point.east() - topLeftCorner.east())   / scale),
-                    (int) Math.round((topLeftCorner.north() - point.north()) / scale)
+                    (int) Math.round((point.east() - anchorPosition.east())   / scale),
+                    (int) Math.round((anchorPosition.north() - point.north()) / scale)
                 );
     }
@@ -302,6 +316,6 @@
         Projection proj = Main.getProjection();
         EastNorth ret = new EastNorth(
-                topLeftCorner.east() + x * scale,
-                topLeftCorner.north() - y * scale
+                anchorPosition.east() + x * scale,
+                anchorPosition.north() - y * scale
                 );
         return proj.eastNorth2latlon(ret).toCoordinate();
@@ -350,6 +364,6 @@
         double scale = getDegreesPerTile(z);
         return new EastNorth(
-                        topLeftCorner.east() + x * scale,
-                        topLeftCorner.north() - y * scale
+                        anchorPosition.east() + x * scale,
+                        anchorPosition.north() - y * scale
                         );
     }
Index: trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java	(revision 9175)
+++ trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java	(revision 9176)
@@ -879,5 +879,5 @@
      */
     private Tile getTile(int x, int y, int zoom) {
-        if (x < 0 || x > tileSource.getTileXMax(zoom) || y < 0 || y > tileSource.getTileYMax(zoom))
+        if (x < tileSource.getTileXMin(zoom) || x > tileSource.getTileXMax(zoom) || y < tileSource.getTileYMin(zoom) || y > tileSource.getTileYMax(zoom))
             return null;
         return tileCache.getTile(tileSource, x, y, zoom);
