Index: /applications/editors/josm/plugins/smed2/jicons/src/jicons/Jicons.java
===================================================================
--- /applications/editors/josm/plugins/smed2/jicons/src/jicons/Jicons.java	(revision 30401)
+++ /applications/editors/josm/plugins/smed2/jicons/src/jicons/Jicons.java	(revision 30402)
@@ -37,5 +37,4 @@
 public class Jicons {
 	
-	static S57map map = null;
 	static int x = 0;
 	static int y = 0;
@@ -45,5 +44,6 @@
 
 	public static void main(String[] args) throws IOException {
-		Render render;
+		Context context;
+		S57map map = null;
 		BufferedReader in;
 		int line = 0;
@@ -64,5 +64,5 @@
 		in = new BufferedReader(new FileReader(args[0]));
 		
-		render = new Render();
+		context = new Context();
 		String ln;
 		while ((ln = in.readLine()) != null) {
@@ -78,5 +78,5 @@
 							img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
 							g2 = img.createGraphics();
-							render.drawRendering(g2, s);
+							Renderer.reRender(g2, 16, s / Renderer.symbolScale[16], map, context);
 							try {
 								ImageIO.write(img, "png", new File(args[1] + file + ".png"));
@@ -92,5 +92,5 @@
 							SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
 							svgGenerator.setSVGCanvasSize(new Dimension(w, h));
-							render.drawRendering(svgGenerator, s);
+							Renderer.reRender(svgGenerator, 16, s / Renderer.symbolScale[16], map, context);
 							boolean useCSS = true;
 							Writer out = null;
@@ -188,10 +188,6 @@
 	}
 	
-	static class Render implements MapContext {
+	static class Context implements MapContext {
 		
-		public void drawRendering(Graphics2D g2, double scale) {
-			Renderer.reRender(g2, 16, scale / Renderer.symbolScale[16], map, this);
-		}
-
 		@Override
 		public Point2D getPoint(Snode coord) {
@@ -201,5 +197,5 @@
 		@Override
 		public double mile(Feature feature) {
-			return 1000;
+			return Math.min(w, h);
 		}
 	}
Index: /applications/editors/josm/plugins/smed2/jrender/src/jrender/Extract.java
===================================================================
--- /applications/editors/josm/plugins/smed2/jrender/src/jrender/Extract.java	(revision 30402)
+++ /applications/editors/josm/plugins/smed2/jrender/src/jrender/Extract.java	(revision 30402)
@@ -0,0 +1,257 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package jrender;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import jrender.Jrender.MapBB;
+
+public class Extract {
+
+	public static ArrayList<String> extractData(String filename, MapBB box) throws IOException {
+
+		HashMap<Long, Long> nodes = new HashMap<Long, Long>();
+		HashMap<Long, Long> ways = new HashMap<Long, Long>();
+		HashMap<Long, Long> rels = new HashMap<Long, Long>();
+
+		ArrayList<String> buf = new ArrayList<String>();
+		BufferedReader in;
+		boolean inOsm = false;
+		boolean inNode = false;
+		boolean inWay = false;
+		boolean inRel = false;
+		
+		double lat = 0;
+		double lon = 0;
+		long id = 0;
+		ArrayList<Long> refs = null;
+		boolean needed = false;
+		String ln;
+
+		in = new BufferedReader(new FileReader(filename));
+		while ((ln = in.readLine()) != null) {
+			if (inOsm) {
+				if (inNode) {
+					if (ln.contains("</node")) {
+						inNode = false;
+					}
+				} else if (ln.contains("<node")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						} else if (token.matches("^lat=.+")) {
+							lat = Double.parseDouble(token.split("[\"\']")[1]);
+						} else if (token.matches("^lon=.+")) {
+							lon = Double.parseDouble(token.split("[\"\']")[1]);
+						}
+					}
+					if ((lat > box.minlat) && (lat <= box.maxlat) && (lon > box.minlon) && (lon <= box.maxlon)) {
+						nodes.put(id, null);
+					}
+					if (!ln.contains("/>")) {
+						inNode = true;
+					}
+				} else if (inWay) {
+					if (ln.contains("<nd")) {
+						long ref = 0;
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^ref=.+")) {
+								ref = Long.parseLong(token.split("[\"\']")[1]);
+								refs.add(ref);
+								if (nodes.containsKey(ref)) {
+									needed = true;
+								}
+							}
+						}
+					}
+					if (ln.contains("</way")) {
+						inWay = false;
+						if (needed) {
+							for (Long nd : refs) {
+								nodes.put(nd, null);
+							}
+							ways.put(id, null);
+						}
+					}
+				} else if (ln.contains("<way")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					refs = new ArrayList<Long>();
+					needed = false;
+					if (!ln.contains("/>")) {
+						inWay = true;
+					}
+				} else if (inRel) {
+					if (ln.contains("<member")) {
+						String type = "";
+						String role = "";
+						long ref = 0;
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^ref=.+")) {
+								ref = Long.parseLong(token.split("[\"\']")[1]);
+							} else if (token.matches("^type=.+")) {
+								type = (token.split("[\"\']")[1]);
+							} else if (token.matches("^role=.+")) {
+								role = (token.split("[\"\']")[1]);
+							}
+						}
+						if ((role.equals("outer") || role.equals("inner")) && type.equals("way")) {
+							needed = ways.containsKey(ref);
+							refs.add(ref);
+						}
+					}
+					if (ln.contains("</relation")) {
+						inRel = false;
+						if (needed) {
+							for (Long way : refs) {
+								ways.put(way, null);
+							}
+							rels.put(id, null);
+						}
+					}
+				} else if (ln.contains("<relation")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					refs = new ArrayList<Long>();
+					needed = false;
+					if (!ln.contains("/>")) {
+						inRel = true;
+					}
+				} else if (ln.contains("</osm")) {
+					inOsm = false;
+					break;
+				}
+			} else if (ln.contains("<osm")) {
+				inOsm = true;
+			}
+		}
+		in.close();
+		
+		in = new BufferedReader(new FileReader(filename));
+		while ((ln = in.readLine()) != null) {
+			if (inOsm) {
+				if (inWay) {
+					if (ln.contains("<nd")) {
+						long ref = 0;
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^ref=.+")) {
+								ref = Long.parseLong(token.split("[\"\']")[1]);
+								if (needed) {
+									nodes.put(ref, null);
+								}
+							}
+						}
+					}
+					if (ln.contains("</way")) {
+						inWay = false;
+					}
+				} else if (ln.contains("<way")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					if (!ln.contains("/>")) {
+						needed = ways.containsKey(id);
+						inWay = true;
+					}
+				} else if (ln.contains("</osm")) {
+					inOsm = false;
+					break;
+				}
+			} else if (ln.contains("<osm")) {
+				inOsm = true;
+			}
+		}
+		in.close();
+		
+		in = new BufferedReader(new FileReader(filename));
+		buf.add("<?xml version='1.0' encoding='UTF-8'?>");
+		buf.add("<osm version='0.6' upload='false' generator='Jrender'>");
+		buf.add(String.format("<bounds minlat='%.8f' minlon='%.8f' maxlat='%.8f' maxlon='%.8f'/>", box.minlat, box.minlon, box.maxlat, box.maxlon));
+		while ((ln = in.readLine()) != null) {
+			if (inOsm) {
+				if (inNode) {
+					buf.add(ln);
+					if (ln.contains("</node")) {
+						inNode = false;
+					}
+				} else if (ln.contains("<node")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					if (nodes.containsKey(id)) {
+						buf.add(ln);
+						if (!ln.contains("/>")) {
+							inNode = true;
+						}
+					}
+				} else if (inWay) {
+					buf.add(ln);
+					if (ln.contains("</way")) {
+						inWay = false;
+					}
+				} else if (ln.contains("<way")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					if (ways.containsKey(id)) {
+						buf.add(ln);
+						if (!ln.contains("/>")) {
+							inWay = true;
+						}
+					}
+				} else if (inRel) {
+					buf.add(ln);
+					if (ln.contains("</relation")) {
+						inRel = false;
+					}
+				} else if (ln.contains("<relation")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					if (rels.containsKey(id)) {
+						buf.add(ln);
+						if (!ln.contains("/>")) {
+							inRel = true;
+						}
+					}
+				} else if (ln.contains("</osm")) {
+					inOsm = false;
+					buf.add(ln);
+					break;
+				}
+			} else {
+				if (ln.contains("<osm")) {
+					inOsm = true;
+				}
+			}
+		}
+		in.close();
+		
+		return buf;
+	}
+}
Index: /applications/editors/josm/plugins/smed2/jrender/src/jrender/Jrender.java
===================================================================
--- /applications/editors/josm/plugins/smed2/jrender/src/jrender/Jrender.java	(revision 30401)
+++ /applications/editors/josm/plugins/smed2/jrender/src/jrender/Jrender.java	(revision 30402)
@@ -1,3 +1,3 @@
-/* Copyright 2012 Malcolm Herring
+/* Copyright 2014 Malcolm Herring
  *
  * This is free software: you can redistribute it and/or modify
@@ -10,230 +10,32 @@
 package jrender;
 
-import java.awt.Dimension;
-import java.awt.Graphics2D;
-import java.awt.geom.Point2D;
-import java.awt.image.BufferedImage;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
 import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.util.zip.GZIPOutputStream;
-
-import javax.imageio.ImageIO;
-
-import org.apache.batik.dom.GenericDOMImplementation;
-import org.apache.batik.svggen.SVGGraphics2D;
-import org.w3c.dom.DOMImplementation;
-import org.w3c.dom.Document;
-
-import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
-
-import s57.S57map;
-import s57.S57map.Feature;
-import s57.S57map.Snode;
-import render.*;
 
 public class Jrender {
 
-	static S57map map = null;
-	static double minlat = 0;
-	static double minlon = 0;
-	static double maxlat = 0;
-	static double maxlon = 0;
-  static double top = 0;
-  static double mile = 0;
-
+	public static class MapBB {
+		public double minlat;
+		public double minlon;
+		public double maxlat;
+		public double maxlon;
+		public MapBB(double nt, double nn, double xt, double xn) {
+			minlat = nt;
+			minlon = nn;
+			maxlat = xt;
+			maxlon = xn;
+		}
+	}
+	
 	public static void main(String[] args) throws IOException {
-		Render render;
-		BufferedReader in;
-		String k = "";
-		String v = "";
-		
-		double lat = 0;
-		double lon = 0;
-		long id = 0;
-
-		BufferedImage img;
-		Graphics2D g2;
-		boolean inOsm = false;
-		boolean inNode = false;
-		boolean inWay = false;
-		boolean inRel = false;
-		
 		if (args.length < 5) {
 			System.err.println("Usage: java -jar jrender.jar osm_file minlat, minlon, maxlat, maxlon");
 			System.exit(-1);
 		}
-		in = new BufferedReader(new FileReader(args[0]));
-		minlat = Double.parseDouble(args[1]);
-		minlon = Double.parseDouble(args[2]);
-		maxlat = Double.parseDouble(args[3]);
-		maxlon = Double.parseDouble(args[4]);
-		top = (1.0 - Math.log(Math.tan(Math.toRadians(maxlat)) + 1.0 / Math.cos(Math.toRadians(maxlat))) / Math.PI) / 2.0 * 256.0 * 4096.0;
-		mile = 768 / ((maxlat - minlat) * 60);
 		
-		render = new Render();
-		String ln;
-		while ((ln = in.readLine()) != null) {
-			if (inOsm) {
-				if ((inNode || inWay || inRel) && (ln.contains("<tag"))) {
-					k = v = "";
-					String[] token = ln.split("k=");
-					k = token[1].split("[\"\']")[1];
-					token = token[1].split("v=");
-					v = token[1].split("[\"\']")[1];
-					if (!k.isEmpty() && !v.isEmpty()) {
-						map.addTag(k, v);
-					}
-				}
-				if (inNode) {
-					if (ln.contains("</node")) {
-						inNode = false;
-						map.tagsDone(id);
-					}
-				} else if (ln.contains("<node")) {
-					for (String token : ln.split("[ ]+")) {
-						if (token.matches("^id=.+")) {
-							id = Long.parseLong(token.split("[\"\']")[1]);
-						} else if (token.matches("^lat=.+")) {
-							lat = Double.parseDouble(token.split("[\"\']")[1]);
-						} else if (token.matches("^lon=.+")) {
-							lon = Double.parseDouble(token.split("[\"\']")[1]);
-						}
-					}
-					map.addNode(id, lat, lon);
-					if (ln.contains("/>")) {
-						map.tagsDone(id);
-					} else {
-						inNode = true;
-					}
-				} else if (inWay) {
-					if (ln.contains("<nd")) {
-						long ref = 0;
-						for (String token : ln.split("[ ]+")) {
-							if (token.matches("^ref=.+")) {
-								ref = Long.parseLong(token.split("[\"\']")[1]);
-							}
-						}
-						map.addToEdge(ref);
-					}
-					if (ln.contains("</way")) {
-						inWay = false;
-						map.tagsDone(id);
-					}
-				} else if (ln.contains("<way")) {
-					for (String token : ln.split("[ ]+")) {
-						if (token.matches("^id=.+")) {
-							id = Long.parseLong(token.split("[\"\']")[1]);
-						}
-					}
-					map.addEdge(id);
-					if (ln.contains("/>")) {
-						map.tagsDone(0);
-					} else {
-						inWay = true;
-					}
-				} else if (ln.contains("</osm")) {
-					inOsm = false;
-					break;
-				} else if (inRel) {
-					if (ln.contains("<member")) {
-						String type = "";
-						String role = "";
-						long ref = 0;
-						for (String token : ln.split("[ ]+")) {
-							if (token.matches("^ref=.+")) {
-								ref = Long.parseLong(token.split("[\"\']")[1]);
-							} else if (token.matches("^type=.+")) {
-								type = (token.split("[\"\']")[1]);
-							} else if (token.matches("^role=.+")) {
-								role = (token.split("[\"\']")[1]);
-							}
-						}
-						if ((role.equals("outer") || role.equals("inner")) && type.equals("way"))
-							map.addToArea(ref, role.equals("outer"));
-					}
-					if (ln.contains("</relation")) {
-						inRel = false;
-						map.tagsDone(id);
-					}
-				} else if (ln.contains("<relation")) {
-					for (String token : ln.split("[ ]+")) {
-						if (token.matches("^id=.+")) {
-							id = Long.parseLong(token.split("[\"\']")[1]);
-						}
-					}
-					map.addArea(id);
-					if (ln.contains("/>")) {
-						map.tagsDone(id);
-					} else {
-						inRel = true;
-					}
-				}
-			} else if (ln.contains("<osm")) {
-				inOsm = true;
-				map = new S57map();
-			}
-		}
-		in.close();
-		
-		for (int s = 1, z = 12; z <= 18; s *= 2, z++) {
-			for (int x = 0; x < s; x++) {
-				for (int y = 0; y < s; y++) {
-					img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
-					g2 = img.createGraphics();
-					g2.scale(s, s);
-					g2.translate(-(256 + (x * 256 / s)), -(256 + (y * 256 / s)));
-					render.drawRendering(g2, z, 1);
-					ByteOutputStream bos = new ByteOutputStream();
-					ImageIO.write(img, "png", bos);
-					if (bos.size() > 334) {
-						FileOutputStream fos = new FileOutputStream("/Users/mherring/boatsw/oseam/josm/plugins/smed2/jrender/tst/tst" + z + "_" + x + "_" + y + ".png");
-						bos.writeTo(fos);
-						fos.close();
-					}
-				}
-			}
-		}
-
-		for (int z = 12; z <= 18; z++) {
-			DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
-			Document document = domImpl.createDocument("http://www.w3.org/2000/svg", "svg", null);
-			SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
-			svgGenerator.setSVGCanvasSize(new Dimension(256, 256));
-			svgGenerator.setClip(0, 0, 256, 256);
-			svgGenerator.translate(-256, -256);
-			render.drawRendering(svgGenerator, z, 1);
-			svgGenerator.stream("/Users/mherring/boatsw/oseam/josm/plugins/smed2/jrender/tst/tst" + z + ".svg");
-		}
+		MapBB bb = new MapBB(Double.parseDouble(args[1]), Double.parseDouble(args[2]), Double.parseDouble(args[3]), Double.parseDouble(args[4]));
+		Tilegen.tileMap(Extract.extractData(args[0], bb), bb);
 
 		System.err.println("Finished");
 		System.exit(0);
 	}
-	
-	
-	static class Render implements MapContext {
-		
-		public void drawRendering(Graphics2D g2, int zoom, double scale) {
-			Renderer.reRender(g2, zoom, scale, map, this);
-		}
-
-		@Override
-		public Point2D getPoint(Snode coord) {
-			double x = (Math.toDegrees(coord.lon) - minlon) * 256.0 * 2048.0 / 180.0;
-			double y = ((1.0 - Math.log(Math.tan(coord.lat) + 1.0 / Math.cos(coord.lat)) / Math.PI) / 2.0 * 256.0 * 4096.0) - top;
-			return new Point2D.Double(x, y);
-		}
-
-		@Override
-		public double mile(Feature feature) {
-			return mile;
-		}
-	}
 }
Index: /applications/editors/josm/plugins/smed2/jrender/src/jrender/Tilegen.java
===================================================================
--- /applications/editors/josm/plugins/smed2/jrender/src/jrender/Tilegen.java	(revision 30402)
+++ /applications/editors/josm/plugins/smed2/jrender/src/jrender/Tilegen.java	(revision 30402)
@@ -0,0 +1,227 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package jrender;
+
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import javax.imageio.ImageIO;
+
+import jrender.Jrender.MapBB;
+
+import org.apache.batik.dom.GenericDOMImplementation;
+import org.apache.batik.svggen.SVGGraphics2D;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+
+import render.MapContext;
+import render.Renderer;
+import s57.S57map;
+import s57.S57map.Feature;
+import s57.S57map.Snode;
+
+public class Tilegen {
+
+	public static void tileMap(ArrayList<String> buf, MapBB bb) throws IOException {
+		Context context;
+		String k = "";
+		String v = "";
+		
+		double lat = 0;
+		double lon = 0;
+		long id = 0;
+
+		BufferedImage img;
+		Graphics2D g2;
+		boolean inOsm = false;
+		boolean inNode = false;
+		boolean inWay = false;
+		boolean inRel = false;
+		
+		context = new Context(bb.minlat, bb.minlon, bb.maxlat, bb.maxlon);
+		S57map map = null;
+
+		for (String ln : buf) {
+			if (inOsm) {
+				if ((inNode || inWay || inRel) && (ln.contains("<tag"))) {
+					k = v = "";
+					String[] token = ln.split("k=");
+					k = token[1].split("[\"\']")[1];
+					token = token[1].split("v=");
+					v = token[1].split("[\"\']")[1];
+					if (!k.isEmpty() && !v.isEmpty()) {
+						map.addTag(k, v);
+					}
+				}
+				if (inNode) {
+					if (ln.contains("</node")) {
+						inNode = false;
+						map.tagsDone(id);
+					}
+				} else if (ln.contains("<node")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						} else if (token.matches("^lat=.+")) {
+							lat = Double.parseDouble(token.split("[\"\']")[1]);
+						} else if (token.matches("^lon=.+")) {
+							lon = Double.parseDouble(token.split("[\"\']")[1]);
+						}
+					}
+					map.addNode(id, lat, lon);
+					if (ln.contains("/>")) {
+						map.tagsDone(id);
+					} else {
+						inNode = true;
+					}
+				} else if (inWay) {
+					if (ln.contains("<nd")) {
+						long ref = 0;
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^ref=.+")) {
+								ref = Long.parseLong(token.split("[\"\']")[1]);
+							}
+						}
+						map.addToEdge(ref);
+					}
+					if (ln.contains("</way")) {
+						inWay = false;
+						map.tagsDone(id);
+					}
+				} else if (ln.contains("<way")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					map.addEdge(id);
+					if (ln.contains("/>")) {
+						map.tagsDone(0);
+					} else {
+						inWay = true;
+					}
+				} else if (ln.contains("</osm")) {
+					inOsm = false;
+					break;
+				} else if (inRel) {
+					if (ln.contains("<member")) {
+						String type = "";
+						String role = "";
+						long ref = 0;
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^ref=.+")) {
+								ref = Long.parseLong(token.split("[\"\']")[1]);
+							} else if (token.matches("^type=.+")) {
+								type = (token.split("[\"\']")[1]);
+							} else if (token.matches("^role=.+")) {
+								role = (token.split("[\"\']")[1]);
+							}
+						}
+						if ((role.equals("outer") || role.equals("inner")) && type.equals("way"))
+							map.addToArea(ref, role.equals("outer"));
+					}
+					if (ln.contains("</relation")) {
+						inRel = false;
+						map.tagsDone(id);
+					}
+				} else if (ln.contains("<relation")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					map.addArea(id);
+					if (ln.contains("/>")) {
+						map.tagsDone(id);
+					} else {
+						inRel = true;
+					}
+				}
+			} else if (ln.contains("<osm")) {
+				inOsm = true;
+				map = new S57map();
+			}
+		}
+		
+		img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
+		Renderer.reRender(img.createGraphics(), 12, 1, map, context);
+		ByteArrayOutputStream bos = new ByteArrayOutputStream();
+		ImageIO.write(img, "png", bos);
+		int empty = bos.size();
+		for (int s = 1, z = 12; z <= 18; s *= 2, z++) {
+			for (int x = 0; x < s; x++) {
+				for (int y = 0; y < s; y++) {
+					img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
+					g2 = img.createGraphics();
+					g2.scale(s, s);
+					g2.translate(-(256 + (x * 256 / s)), -(256 + (y * 256 / s)));
+					Renderer.reRender(g2, z, 1, map, context);
+					bos = new ByteArrayOutputStream();
+					ImageIO.write(img, "png", bos);
+					if (bos.size() > empty) {
+						FileOutputStream fos = new FileOutputStream("/Users/mherring/boatsw/oseam/josm/plugins/smed2/jrender/tst/tst" + z + "_" + x + "_" + y + ".png");
+						bos.writeTo(fos);
+						fos.close();
+					}
+				}
+			}
+		}
+
+		for (int z = 12; z <= 18; z++) {
+			DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
+			Document document = domImpl.createDocument("http://www.w3.org/2000/svg", "svg", null);
+			SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
+			svgGenerator.setSVGCanvasSize(new Dimension(256, 256));
+			svgGenerator.setClip(0, 0, 256, 256);
+			svgGenerator.translate(-256, -256);
+			Renderer.reRender(svgGenerator, z, 1, map, context);
+			svgGenerator.stream("/Users/mherring/boatsw/oseam/josm/plugins/smed2/jrender/tst/tst_" + z + ".svg");
+		}
+
+	}
+	
+	static class Context implements MapContext {
+		
+		static double minlat = 0;
+		static double minlon = 0;
+		static double maxlat = 0;
+		static double maxlon = 0;
+	  static double top = 0;
+	  static double mile = 0;
+	  
+	  public Context (double nt, double nn, double xt, double xn) {
+			minlat = nt;
+			minlon = nn;
+			maxlat = xt;
+			maxlon = xn;
+			top = (1.0 - Math.log(Math.tan(Math.toRadians(maxlat)) + 1.0 / Math.cos(Math.toRadians(maxlat))) / Math.PI) / 2.0 * 256.0 * 4096.0;
+			mile = 768 / ((maxlat - minlat) * 60);
+	  }
+	  
+		@Override
+		public Point2D getPoint(Snode coord) {
+			double x = (Math.toDegrees(coord.lon) - minlon) * 256.0 * 2048.0 / 180.0;
+			double y = ((1.0 - Math.log(Math.tan(coord.lat) + 1.0 / Math.cos(coord.lat)) / Math.PI) / 2.0 * 256.0 * 4096.0) - top;
+			return new Point2D.Double(x, y);
+		}
+
+		@Override
+		public double mile(Feature feature) {
+			return mile;
+		}
+		
+	}
+}
