Index: uk/me/parabola/imgfmt/app/map/MapReader.java
===================================================================
--- uk/me/parabola/imgfmt/app/map/MapReader.java	(revision 2540)
+++ uk/me/parabola/imgfmt/app/map/MapReader.java	(working copy)
@@ -31,10 +31,12 @@
 import uk.me.parabola.imgfmt.app.net.NETFileReader;
 import uk.me.parabola.imgfmt.app.net.RoadDef;
 import uk.me.parabola.imgfmt.app.trergn.Point;
+import uk.me.parabola.imgfmt.app.trergn.Polygon;
 import uk.me.parabola.imgfmt.app.trergn.Polyline;
 import uk.me.parabola.imgfmt.app.trergn.RGNFileReader;
 import uk.me.parabola.imgfmt.app.trergn.Subdivision;
 import uk.me.parabola.imgfmt.app.trergn.TREFileReader;
+import uk.me.parabola.imgfmt.app.trergn.Zoom;
 import uk.me.parabola.imgfmt.fs.DirectoryEntry;
 import uk.me.parabola.imgfmt.fs.FileSystem;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
@@ -47,13 +49,13 @@
  * @author Steve Ratcliffe
  */
 public class MapReader implements Closeable {
-	private final TREFileReader treFile;
-	private final RGNFileReader rgnFile;
-	private final LBLFileReader lblFile;
+	private final TREFileReader treFile;
+	private final RGNFileReader rgnFile;
+	private final LBLFileReader lblFile;
 	private final NETFileReader netFile;
-
-	private final Deque<Closeable> toClose = new ArrayDeque<Closeable>();
-
+
+	private final Deque<Closeable> toClose = new ArrayDeque<Closeable>();
+
 	public MapReader(String filename) throws FileNotFoundException {
 		FileSystem fs = ImgFS.openFs(filename);
 		saveForClose(fs);
@@ -93,15 +95,15 @@
 			nr.setCities(lblFile.getCities());
 			nr.setZips(lblFile.getZips());
 			saveForClose(nr);
-		} catch (FileNotFoundException e) {
-			nr = null;
-		}
+		} catch (FileNotFoundException e) {
+			nr = null;
+		}
 		netFile = nr;
-
+
 		rgnFile.setNetFile(netFile);
-		rgnFile.setLblFile(lblFile);
-	}
-
+		rgnFile.setLblFile(lblFile);
+	}
+
 	/**
 	 * Get a list of all the points for a given level.
 	 * @param level The level, lower numbers are the most detailed.
@@ -115,12 +117,16 @@
 			points.addAll(subdivPoints);
 		}
 
-		return points;
-	}
-
-	/**
-	 * Get a list of all the lines for a given level.
-	 * @param level The level, lower numbers are the most detailed.
+		return points;
+	}
+
+	public Zoom[] getLevels() {
+		return treFile.getMapLevels();
+	}
+
+	/**
+	 * Get a list of all the lines for a given level.
+	 * @param level The level, lower numbers are the most detailed.
 	 */
 	public List<Polyline> linesForLevel(int level) {
 		ArrayList<Polyline> points = new ArrayList<Polyline>();
@@ -131,14 +137,27 @@
 			points.addAll(subdivPoints);
 		}
 
-		return points;
-	}
-
-	public void close() throws IOException {
-		for (Closeable c : toClose)
-			Utils.closeFile(c);
-	}
-
+		return points;
+	}
+
+
+	public List<Polygon> shapesForLevel(int level) {
+		ArrayList<Polygon> points = new ArrayList<Polygon>();
+
+		Subdivision[] subdivisions = treFile.subdivForLevel(level);
+		for (Subdivision div : subdivisions) {
+			List<Polygon> subdivPoints = rgnFile.shapesForSubdiv(div);
+			points.addAll(subdivPoints);
+		}
+
+		return points;
+	}
+
+	public void close() throws IOException {
+		for (Closeable c : toClose)
+			Utils.closeFile(c);
+	}
+
 	private void saveForClose(Closeable c1, Closeable c2) {
 		saveForClose(c1);
 		saveForClose(c2);
Index: uk/me/parabola/imgfmt/app/trergn/Point.java
===================================================================
--- uk/me/parabola/imgfmt/app/trergn/Point.java	(revision 2540)
+++ uk/me/parabola/imgfmt/app/trergn/Point.java	(working copy)
@@ -19,6 +19,7 @@
 import java.io.IOException;
 import java.io.OutputStream;
 
+import uk.me.parabola.imgfmt.app.Coord;
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
 import uk.me.parabola.imgfmt.app.lbl.POIRecord;
 
@@ -122,4 +123,11 @@
 			return new POIRecord();
 		return poi;
 	}
+
+	public Coord getLocation() {
+		int shift = getSubdiv().getShift();
+		Coord co = new Coord(getSubdiv().getLatitude() + (getDeltaLat() << shift), 
+				getSubdiv().getLongitude() + (getDeltaLong() << shift) );
+		return co;
+	}
 }
Index: uk/me/parabola/imgfmt/app/trergn/Polyline.java
===================================================================
--- uk/me/parabola/imgfmt/app/trergn/Polyline.java	(revision 2540)
+++ uk/me/parabola/imgfmt/app/trergn/Polyline.java	(working copy)
@@ -222,7 +222,7 @@
 		points.addAll(coords);
 	}
 
-	List<Coord> getPoints() {
+	public List<Coord> getPoints() {
 		return points;
 	}
 
@@ -265,8 +265,16 @@
 					if (p1.getId() == p2.getId())
 						return true;
 			}
-		}
-
-		return false;
-	}
-}
+		}
+
+		return false;
+	}
+
+	public int getLat() {
+		return getSubdiv().getLatitude() + (getDeltaLat() << getSubdiv().getShift());
+	}
+
+	public int getLong() {
+		return getSubdiv().getLongitude() + (getDeltaLong() << getSubdiv().getShift());
+	}
+}
Index: uk/me/parabola/imgfmt/app/trergn/RGNFileReader.java
===================================================================
--- uk/me/parabola/imgfmt/app/trergn/RGNFileReader.java	(revision 2540)
+++ uk/me/parabola/imgfmt/app/trergn/RGNFileReader.java	(working copy)
@@ -16,7 +16,11 @@
 import java.util.Collections;
 import java.util.List;
 
+import uk.me.parabola.imgfmt.Utils;
+import uk.me.parabola.imgfmt.app.BitReader;
 import uk.me.parabola.imgfmt.app.BufferedImgFileReader;
+import uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.imgfmt.app.CoordNode;
 import uk.me.parabola.imgfmt.app.ImgFileReader;
 import uk.me.parabola.imgfmt.app.ImgReader;
 import uk.me.parabola.imgfmt.app.Label;
@@ -25,6 +29,7 @@
 import uk.me.parabola.imgfmt.app.net.NETFileReader;
 import uk.me.parabola.imgfmt.app.net.RoadDef;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
+import uk.me.parabola.log.Logger;
 import uk.me.parabola.util.EnhancedProperties;
 
 /**
@@ -40,6 +45,7 @@
  * @author Steve Ratcliffe
  */
 public class RGNFileReader extends ImgReader {
+	private static final Logger log = Logger.getLogger(RGNFileReader.class);
 
 	private final RGNHeader rgnHeader;
 	private LBLFileReader lblFile;
@@ -131,6 +137,11 @@
 		}
 	}
 
+	/**
+	 * Get all the lines for a given subdivision.
+	 * @param div The subdivision we want the line from.
+	 * @return A list of lines.
+	 */
 	public List<Polyline> linesForSubdiv(Subdivision div) {
 		if (!div.hasPolylines())
 			return Collections.emptyList();
@@ -145,39 +156,177 @@
 		ImgFileReader reader = getReader();
 		while (position() < end) {
 			Polyline line = new Polyline(div);
-			byte type = reader.get();
-			line.setType(type & 0x3f);
+			readLineCommon(reader, div, line);
+			list.add(line);
+		}
 
-			int labelOffset = reader.getu3();
-			Label label;
-			if ((labelOffset & 0x800000) == 0) {
-				label = lblFile.fetchLabel(labelOffset & 0x7fffff);
-			} else {
+		return list;
+	}
+
+	/**
+	 * Get all the polygons for a given subdivision.
+	 */
+	public List<Polygon> shapesForSubdiv(Subdivision div) {
+		if (!div.hasPolygons())
+			return Collections.emptyList();
+
+		RgnOffsets rgnOffsets = getOffsets(div);
+		ArrayList<Polygon> list = new ArrayList<Polygon>();
+
+		int start = rgnOffsets.getPolygonStart();
+		int end = rgnOffsets.getPolygonEnd();
+
+		position(start);
+		ImgFileReader reader = getReader();
+
+		while (position() < end) {
+			Polygon line = new Polygon(div);
+			readLineCommon(reader, div, line);
+			list.add(line);
+		}
+
+		return list;
+	}
+
+	/**
+	 * Since polygons are pretty much like polylines in the img format the
+	 * reading code can be shared.
+	 *
+	 * @param reader The reader for the img file.
+	 * @param div The subdivision.
+	 * @param line The line or shape that is to be populated.
+	 */
+	private void readLineCommon(ImgFileReader reader, Subdivision div, Polyline line) {
+		byte type = reader.get();
+		line.setType(type & 0x7f);
+
+		int labelOffset = reader.getu3();
+		Label label;
+		if ((labelOffset & 0x800000) == 0) {
+			label = lblFile.fetchLabel(labelOffset & 0x7fffff);
+		} else {
 				int netoff = labelOffset & 0x3fffff;
 				labelOffset = netFile.getLabelOffset(netoff);
 				label = lblFile.fetchLabel(labelOffset);
 				RoadDef roadDef = new RoadDef(0, netoff, label.getText());
 				line.setRoadDef(roadDef);
+		}
+		line.setLabel(label);
+
+		// Extra bit (for bit stream)
+		boolean extra = (labelOffset & 0x400000) != 0;
+
+		line.setDeltaLong((short)reader.getChar());
+		line.setDeltaLat((short)reader.getChar());
+
+		int len;
+		if ((type & 0x80) == 0)
+			len = reader.get() & 0xff;
+		else
+			len = reader.getChar();
+
+		int base = reader.get();
+
+		byte[] bitstream = reader.get(len);
+		BitReader br = new BitReader(bitstream);
+
+		// This reads the bit stream and adds all the points found
+		readBitStream(br, div, line, extra, len, base);
+	}
+
+
+	/**
+	 * Read the bit stream for a single line in the file.
+	 * @param br The bit stream reader.
+	 * @param div The subdivision that the line is in.
+	 * @param line The line itself.
+	 * @param extra True if there is an 'extra' bit in the stream. Used for nodes.
+	 * @param len The length of the stream.
+	 * @param base The base size of the deltas.
+	 */
+	private void readBitStream(BitReader br, Subdivision div, Polyline line, boolean extra, int len, int base) {
+		int currLat = line.getLat();
+		int currLon = line.getLong();
+
+		log.debug(String.format("Start point %.5f,%.5f",
+				Utils.toDegrees(currLat),
+				Utils.toDegrees(currLon)));
+
+		int xbase = 2;
+		int n = base & 0xf;
+		if (n <= 9)
+			xbase += n;
+		else
+			xbase += (2 * n) - 9;
+
+		n = (base >>> 4) & 0xf;
+		int ybase = 2;
+		if (n <= 9)
+			ybase += n;
+		else
+			ybase += (2 * n) - 9;
+
+		if (len == 0)
+			return;
+
+		boolean xneg = false;
+		boolean xsame = br.get1();
+		if (xsame) {
+			xneg = br.get1();
+		} else
+			xbase++;
+
+		boolean ysame = br.get1();
+		boolean yneg = false;
+		if (ysame) {
+			yneg = br.get1();
+		} else
+			ybase++;
+
+		if (extra) {
+			boolean firstextra = br.get1();
+			log.debug("the first extra bit is", firstextra);
+		}
+
+		// All is now prepared, read the actual deltas and decode them into
+		// proper lat/long coords.
+		while (br.getBitPosition() <= 8* len - ((extra ? 1:0) + xbase + ybase)) {
+			br.getBitPosition();
+
+			int dx;
+			if (xsame) {
+				dx = br.get(xbase);
+				if (xneg)
+					dx = -dx;
+			} else {
+				dx = br.sget2(xbase);
 			}
-			line.setLabel(label);
 
-			line.setDeltaLong((short)reader.getChar());
-			line.setDeltaLat((short)reader.getChar());
+			int dy;
+			if (ysame) {
+				dy = br.get(ybase);
+				if (yneg)
+					dy = -dy;
+			} else {
+				dy = br.sget2(ybase);
+			}
 
-			int len;
-			if ((type & 0x80) == 0)
-				len = reader.get() & 0xff;
+			boolean isnode = false;
+			if (extra)
+				isnode = br.get1();
+
+			currLat += dy << (24 - div.getResolution());
+			currLon += dx << (24 - div.getResolution());
+			Coord coord;
+			if (isnode)
+				coord = new CoordNode(currLat, currLon, 0/* XXX */, false);
 			else
-				len = reader.getChar();
+				coord = new Coord(currLat, currLon);
 
-			reader.get(len + 1);
-
-			//System.out.println("add line " + line);
-			list.add(line);
+			line.addCoord(coord);
 		}
+	}
 
-		return list;
-	}
 	/**
 	 * Get the offsets to the points, lines etc in RGN for the given subdiv.
 	 * @param sd The subdivision is needed to work out the starting points.
@@ -306,5 +455,13 @@
 		public int getLineEnd() {
 			return start + lineEnd;
 		}
+
+		public int getPolygonStart() {
+			return polygonOffset == 0? start + headerLen: start + polygonOffset;
+		}
+
+		public int getPolygonEnd() {
+			return start + polygonEnd;
+		}
 	}
 }
Index: uk/me/parabola/imgfmt/app/trergn/TREFileReader.java
===================================================================
--- uk/me/parabola/imgfmt/app/trergn/TREFileReader.java	(revision 2540)
+++ uk/me/parabola/imgfmt/app/trergn/TREFileReader.java	(working copy)
@@ -53,12 +53,16 @@
 	}
 
 	public Area getBounds() {
-		return header.getBounds();
-	}
-
-	/**
-	 * Return the subdivisions for the given level.
-	 * @param level The level, 0 being the most detailed.  There may not be
+		return header.getBounds();
+	}
+
+	public Zoom[] getMapLevels() {
+		return mapLevels;
+	}
+	
+	/**
+	 * Return the subdivisions for the given level.
+	 * @param level The level, 0 being the most detailed.  There may not be
 	 * a level zero in the map.
 	 * @return The subdivisions for the level. Never returns null; a zero length
 	 * array is returned if there is no such level.
@@ -84,12 +88,13 @@
 
 		int subdivNum = 1;
 		int lastRgnOffset = reader.getu3();
-		for (int count = 0; count < levelDivs.length && reader.position() < end; count++) {
-
-			Subdivision[] divs = levelDivs[count];
-			if (divs == null)
-				break;
-
+		for (int count = 0; count < levelDivs.length && reader.position() < end; count++) {
+
+			Subdivision[] divs = levelDivs[count];
+			Zoom zoom = mapLevels[count];
+			if (divs == null)
+				break;
+
 			for (int i = 0; i < divs.length; i++) {
 				int flags = reader.get();
 				int lon = reader.get3();
@@ -107,12 +112,13 @@
 						lastRgnOffset, endRgnOffset);
 
 				Subdivision subdiv = Subdivision.readSubdivision(mapLevels[count], subdivData);
-				subdiv.setNumber(subdivNum++);
-				
-				divs[i] = subdiv;
-
-				lastRgnOffset = endRgnOffset;
-			}
+				subdiv.setNumber(subdivNum++);
+				
+				divs[i] = subdiv;
+				zoom.addSubdivision(subdiv);
+
+				lastRgnOffset = endRgnOffset;
+			}
 		}
 	}
 
Index: uk/me/parabola/mkgmap/combiners/OverviewBuilder.java
===================================================================
--- uk/me/parabola/mkgmap/combiners/OverviewBuilder.java	(revision 0)
+++ uk/me/parabola/mkgmap/combiners/OverviewBuilder.java	(working copy)
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+package uk.me.parabola.mkgmap.combiners;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+
+import uk.me.parabola.imgfmt.ExitException;
+import uk.me.parabola.imgfmt.FileExistsException;
+import uk.me.parabola.imgfmt.FileNotWritableException;
+import uk.me.parabola.imgfmt.FileSystemParam;
+import uk.me.parabola.imgfmt.MapFailedException;
+import uk.me.parabola.imgfmt.app.Area;
+import uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.imgfmt.app.map.Map;
+import uk.me.parabola.imgfmt.app.map.MapReader;
+import uk.me.parabola.imgfmt.app.srt.Sort;
+import uk.me.parabola.imgfmt.app.trergn.Point;
+import uk.me.parabola.imgfmt.app.trergn.Polygon;
+import uk.me.parabola.imgfmt.app.trergn.Polyline;
+import uk.me.parabola.imgfmt.app.trergn.Zoom;
+import uk.me.parabola.log.Logger;
+import uk.me.parabola.mkgmap.CommandArgs;
+import uk.me.parabola.mkgmap.build.MapBuilder;
+import uk.me.parabola.mkgmap.general.MapLine;
+import uk.me.parabola.mkgmap.general.MapPoint;
+import uk.me.parabola.mkgmap.general.MapShape;
+
+/**
+ * Build the overview map.  This is a low resolution map that covers the whole
+ * of a map set.  It also contains polygons that correspond to the areas
+ * covered by the individual map tiles.
+ *
+ * @author Steve Ratcliffe
+ */
+public class OverviewBuilder implements Combiner {
+	Logger log = Logger.getLogger(OverviewBuilder.class);
+
+	private final OverviewMap overviewSource;
+	private String areaName;
+	private String overviewMapname;
+	private String overviewMapnumber;
+	private Zoom[] levels;
+	private String outputDir;		
+	private Sort sort;
+	private boolean addPoints = false;
+	private boolean addLines = false;
+	private boolean addPolygons = false;
+
+	public OverviewBuilder(OverviewMap overviewSource) {
+		this.overviewSource = overviewSource;
+	}
+
+	public void init(CommandArgs args) {
+		areaName = args.get("area-name", "Overview Map");
+		overviewMapname = args.get("overview-mapname", "osmmap");
+		overviewMapnumber = args.get("overview-mapnumber", "63240000");
+		outputDir = args.getOutputDir();
+		sort = args.getSort();
+		addPoints = args.getProperties().containsKey("overview-add-points");
+		addLines = args.getProperties().containsKey("overview-add-lines");
+		addPolygons = args.getProperties().containsKey("overview-add-polygons");
+		
+	}
+
+	public void onMapEnd(FileInfo finfo) {
+		if (!finfo.isImg())
+			return;
+
+		try {
+			readFileIntoOverview(finfo);
+		} catch (FileNotFoundException e) {
+			throw new MapFailedException("Could not read detail map " + finfo.getFilename(), e);
+		}
+	}
+
+	public void onFinish() {
+		writeOverviewMap();
+	}
+
+	/**
+	 * Write out the overview map.
+	 */
+	private void writeOverviewMap() {
+		MapBuilder mb = new MapBuilder();
+		mb.setEnableLineCleanFilters(false);
+
+		FileSystemParam params = new FileSystemParam();
+		params.setBlockSize(512);
+		params.setMapDescription(areaName);
+
+		try {
+			Map map = Map.createMap(overviewMapname, outputDir, params, overviewMapnumber, sort);
+			mb.makeMap(map, overviewSource);
+			map.close();
+		} catch (FileExistsException e) {
+			throw new ExitException("Could not create overview map", e);
+		} catch (FileNotWritableException e) {
+			throw new ExitException("Could not write to overview map", e);
+		}
+	}
+
+	/**
+	 * Add an individual .img file to the overview map.
+	 *
+	 * @param finfo Information about an individual map.
+	 */
+	private void readFileIntoOverview(FileInfo finfo) throws FileNotFoundException {
+		addMapCoverageArea(finfo);
+
+		MapReader mapReader = new MapReader(finfo.getFilename());
+
+		levels = mapReader.getLevels();
+
+		if (addPoints)
+			readPoints(mapReader);
+		if (addLines)
+			readLines(mapReader);
+		if (addPolygons)
+			readShapes(mapReader);
+	}
+
+	/**
+	 * Read the points from the .img file and add them to the overview map.
+	 * We read from the least detailed level (apart from the empty one).
+	 *
+	 * TODO: further filter what is seen
+	 *
+	 * @param mapReader Map reader on the detailed .img file.
+	 */
+	private void readPoints(MapReader mapReader) {
+		int min = levels[1].getLevel();
+		List<Point> pointList = mapReader.pointsForLevel(min);
+		for (Point point: pointList) {
+			log.debug("got point", point);
+			MapPoint mp = new MapPoint();
+
+			mp.setType(point.getType());
+			mp.setName(point.getLabel().getText());
+			mp.setMaxResolution(24); // TODO
+			mp.setMinResolution(5);  // TODO
+			mp.setLocation(point.getLocation());
+			overviewSource.addPoint(mp);
+		}
+	}
+
+	/**
+	 * Read the lines from the .img file and add them to the overview map.
+	 * We read from the least detailed level (apart from the empty one).
+	 *
+	 * TODO: further filter what is seen
+	 *
+	 * @param mapReader Map reader on the detailed .img file.
+	 */
+	private void readLines(MapReader mapReader) {
+		int min = levels[1].getLevel();
+		List<Polyline> lineList = mapReader.linesForLevel(min);
+		for (Polyline line : lineList) {
+			log.debug("got line", line);
+			MapLine ml = new MapLine();
+
+			List<Coord> list = line.getPoints();
+			log.debug("line point list", list);
+			if (list.size() < 2)
+				continue;
+
+			ml.setType(line.getType());
+			ml.setName(line.getLabel().getText());
+			ml.setMaxResolution(24); // TODO
+			ml.setMinResolution(5);  // TODO
+			ml.setPoints(list);
+			
+			overviewSource.addLine(ml);
+		}
+	}
+
+	private void readShapes(MapReader mapReader) {
+		int min = levels[1].getLevel();
+		List<Polygon> list = mapReader.shapesForLevel(min);
+		for (Polygon shape : list) {
+			MapShape ms = new MapShape();
+
+			List<Coord> points = shape.getPoints();
+			if (points.size() < 2)
+				continue;
+
+			ms.setType(shape.getType());
+			ms.setName(shape.getLabel().getText());
+			ms.setMaxResolution(24); // TODO
+			ms.setMinResolution(5);  // TODO
+			ms.setPoints(points);
+
+			overviewSource.addShape(ms);
+		}
+	}
+
+	/**
+	 * Add an area that shows the area covered by a detailed map.  This can
+	 * be an arbitary shape, although at the current time we only support
+	 * rectangles.
+	 *
+	 * @param finfo Information about a detail map.
+	 */
+	private void addMapCoverageArea(FileInfo finfo) {
+		Area bounds = finfo.getBounds();
+
+		int maxLon = bounds.getMaxLong();
+		int maxLat = bounds.getMaxLat();
+		int minLat = bounds.getMinLat();
+		int minLon = bounds.getMinLong();
+ 
+		// Add a background polygon for this map.
+		List<Coord> points = new ArrayList<Coord>();
+
+		Coord start = new Coord(minLat, minLon);
+		points.add(start);
+		overviewSource.addToBounds(start);
+
+		Coord co = new Coord(maxLat, minLon);
+		points.add(co);
+		overviewSource.addToBounds(co);
+
+		co = new Coord(maxLat, maxLon);
+		points.add(co);
+		overviewSource.addToBounds(co);
+
+		co = new Coord(minLat, maxLon);
+		points.add(co);
+		overviewSource.addToBounds(co);
+
+		points.add(start);
+
+		// Create the background rectangle
+		MapShape bg = new MapShape();
+		bg.setType(0x4a);
+		bg.setPoints(points);
+		bg.setMinResolution(10);
+		bg.setName(finfo.getDescription() + '\u001d' + finfo.getMapname());
+
+		overviewSource.addShape(bg);  	}
+
+	public Area getBounds() {
+		return overviewSource.getBounds();
+	}
+}
Index: uk/me/parabola/mkgmap/combiners/TdbBuilder.java
===================================================================
--- uk/me/parabola/mkgmap/combiners/TdbBuilder.java	(revision 2540)
+++ uk/me/parabola/mkgmap/combiners/TdbBuilder.java	(working copy)
@@ -17,22 +17,10 @@
 package uk.me.parabola.mkgmap.combiners;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
 import uk.me.parabola.imgfmt.ExitException;
-import uk.me.parabola.imgfmt.FileExistsException;
-import uk.me.parabola.imgfmt.FileNotWritableException;
-import uk.me.parabola.imgfmt.FileSystemParam;
 import uk.me.parabola.imgfmt.Utils;
-import uk.me.parabola.imgfmt.app.Area;
-import uk.me.parabola.imgfmt.app.Coord;
-import uk.me.parabola.imgfmt.app.map.Map;
-import uk.me.parabola.imgfmt.app.srt.Sort;
 import uk.me.parabola.log.Logger;
 import uk.me.parabola.mkgmap.CommandArgs;
-import uk.me.parabola.mkgmap.build.MapBuilder;
-import uk.me.parabola.mkgmap.general.MapShape;
 import uk.me.parabola.tdbfmt.DetailMapBlock;
 import uk.me.parabola.tdbfmt.TdbFile;
 
@@ -44,19 +32,21 @@
 public class TdbBuilder implements Combiner {
 	private static final Logger log = Logger.getLogger(TdbBuilder.class);
 
-	private OverviewMap overviewSource;
+	private final OverviewBuilder overviewBuilder;
 	
 	private TdbFile tdb;
 
 	private int parent = 63240000;
 	private String overviewMapname;
 	private String overviewMapnumber;
-	private String areaName;
 	private String outputDir;
 	private int tdbVersion;
 
-	private Sort sort;
+	public TdbBuilder(OverviewBuilder ovb) {
+		overviewBuilder = ovb;
+	}
 
+
 	/**
 	 * Initialise by saving all the information we require from the command line
 	 * args.
@@ -73,9 +63,9 @@
 		} catch (NumberFormatException e) {
 			log.debug("overview map number not an integer", overviewMapnumber);
 		}
-
-		areaName = args.get("area-name", "Overview Map");
-
+
+		String areaName = args.get("area-name", "Overview Map");
+
 		int familyId = args.get("family-id", CommandArgs.DEFAULT_FAMILYID);
 		int productId = args.get("product-id", 1);
 		short productVersion = (short)args.get("product-version", 100);
@@ -94,8 +84,6 @@
 				familyName, areaName, enableProfile);
 		
 		outputDir = args.getOutputDir();
-
-		sort = args.getSort();
 	}
 
 	/**
@@ -109,7 +97,6 @@
 			return;
 		
 		addToTdb(info);
-		addToOverviewMap(info);
 	}
 
 	/**
@@ -146,50 +133,6 @@
 	}
 
 	/**
-	 * Add an individual .img file to the overview map.
-	 *
-	 * @param finfo Information about an individual map.
-	 */
-	private void addToOverviewMap(FileInfo finfo) {
-		Area bounds = finfo.getBounds();
-
-		int maxLon = bounds.getMaxLong();
-		int maxLat = bounds.getMaxLat();
-		int minLat = bounds.getMinLat();
-		int minLon = bounds.getMinLong();
-
-		// Add a background polygon for this map.
-		List<Coord> points = new ArrayList<Coord>();
-
-		Coord start = new Coord(minLat, minLon);
-		points.add(start);
-		overviewSource.addToBounds(start);
-
-		Coord co = new Coord(maxLat, minLon);
-		points.add(co);
-		overviewSource.addToBounds(co);
-
-		co = new Coord(maxLat, maxLon);
-		points.add(co);
-		overviewSource.addToBounds(co);
-
-		co = new Coord(minLat, maxLon);
-		points.add(co);
-		overviewSource.addToBounds(co);
-
-		points.add(start);
-
-		// Create the background rectangle
-		MapShape bg = new MapShape();
-		bg.setType(0x4a);
-		bg.setPoints(points);
-		bg.setMinResolution(10);
-		bg.setName(finfo.getDescription() + '\u001d' + finfo.getMapname());
-
-		overviewSource.addShape(bg);
-	}
-
-	/**
 	 * Called when all the .img files have been processed.  We finish up and
 	 * create the TDB file and the overview map.
 	 */
@@ -198,48 +141,20 @@
 
 		// We can set the overall bounds easily as it was calculated as part of
 		// the overview map.
-		tdb.setOverview(overviewSource.getBounds(), overviewMapnumber);
+		tdb.setOverview(overviewBuilder.getBounds(), overviewMapnumber);
 
 		writeTdbFile();
-		writeOverviewMap();
 	}
 
 	/**
-	 * Write out the overview map.
-	 */
-	private void writeOverviewMap() {
-		MapBuilder mb = new MapBuilder();
-		mb.setEnableLineCleanFilters(false);
-
-		FileSystemParam params = new FileSystemParam();
-		params.setBlockSize(512);
-		params.setMapDescription(areaName);
-
-		try {
-			Map map = Map.createMap(overviewMapname, outputDir, params, overviewMapnumber, sort);
-			map.setSort(sort);
-			mb.makeMap(map, overviewSource);
-			map.close();
-		} catch (FileExistsException e) {
-			throw new ExitException("Could not create overview map", e);
-		} catch (FileNotWritableException e) {
-			throw new ExitException("Could not write to overview map", e);
-		}
-	}
-
-	/**
 	 * Write out the TDB file at the end of processing.
 	 */
 	private void writeTdbFile() {
 		try {
 			tdb.write(Utils.joinPath(outputDir, overviewMapname, "tdb"));
 		} catch (IOException e) {
-			log.error("tdb write", e);
-			throw new ExitException("Could not write the TDB file", e);
-		}
-	}
-
-	public void setOverviewSource(OverviewMap overviewSource) {
-		this.overviewSource = overviewSource;
-	}
-}
+			log.error("tdb write", e);
+			throw new ExitException("Could not write the TDB file", e);
+		}
+	}
+}
Index: uk/me/parabola/mkgmap/main/Main.java
===================================================================
--- uk/me/parabola/mkgmap/main/Main.java	(revision 2540)
+++ uk/me/parabola/mkgmap/main/Main.java	(working copy)
@@ -47,12 +47,14 @@
 import uk.me.parabola.mkgmap.combiners.Combiner;
 import uk.me.parabola.mkgmap.combiners.FileInfo;
 import uk.me.parabola.mkgmap.combiners.GmapsuppBuilder;
-import uk.me.parabola.mkgmap.combiners.MdrBuilder;
-import uk.me.parabola.mkgmap.combiners.MdxBuilder;
-import uk.me.parabola.mkgmap.combiners.NsisBuilder;
-import uk.me.parabola.mkgmap.combiners.TdbBuilder;
-import uk.me.parabola.mkgmap.osmstyle.StyleFileLoader;
-import uk.me.parabola.mkgmap.osmstyle.StyleImpl;
+import uk.me.parabola.mkgmap.combiners.MdrBuilder;
+import uk.me.parabola.mkgmap.combiners.MdxBuilder;
+import uk.me.parabola.mkgmap.combiners.NsisBuilder;
+import uk.me.parabola.mkgmap.combiners.OverviewBuilder;
+import uk.me.parabola.mkgmap.combiners.OverviewMap;
+import uk.me.parabola.mkgmap.combiners.TdbBuilder;
+import uk.me.parabola.mkgmap.osmstyle.StyleFileLoader;
+import uk.me.parabola.mkgmap.osmstyle.StyleImpl;
 import uk.me.parabola.mkgmap.reader.osm.Style;
 import uk.me.parabola.mkgmap.reader.osm.StyleInfo;
 import uk.me.parabola.mkgmap.reader.overview.OverviewMapDataSource;
@@ -278,14 +280,22 @@
 	}
 
 	public void removeOption(String opt) {
-	}
-
-	private void addTdbBuilder() {
-		TdbBuilder builder = new TdbBuilder();
-		builder.setOverviewSource(new OverviewMapDataSource());
-		addCombiner(builder);
-	}
-
+	}
+
+	/**
+	 * Add the builders for the TDB and overview map.  These are always
+	 * generated together as we use some info that is calculated when constructing
+	 * the overview map in the TDB file.
+	 */
+	private void addTdbBuilder() {
+		OverviewMap overviewSource = new OverviewMapDataSource();
+		OverviewBuilder overviewBuilder = new OverviewBuilder(overviewSource);
+		addCombiner(overviewBuilder);
+		
+		TdbBuilder tdbBuilder = new TdbBuilder(overviewBuilder);
+		addCombiner(tdbBuilder);
+	}
+
 	private void listStyles() {
 
 		String[] names;
