Index: /applications/editors/josm/plugins/smed2/src/seamap/Renderer.java
===================================================================
--- /applications/editors/josm/plugins/smed2/src/seamap/Renderer.java	(revision 29825)
+++ /applications/editors/josm/plugins/smed2/src/seamap/Renderer.java	(revision 29826)
@@ -11,4 +11,5 @@
 
 import java.awt.*;
+import java.awt.font.*;
 import java.awt.geom.*;
 import java.util.*;
@@ -25,5 +26,5 @@
 
 public class Renderer {
-	
+
 	static MapHelper helper;
 	static SeaMap map;
@@ -32,5 +33,5 @@
 	static Graphics2D g2;
 	static int zoom;
-	
+
 	public static void reRender(Graphics2D g, int z, double factor, SeaMap m, MapHelper h) {
 		g2 = g;
@@ -38,6 +39,6 @@
 		helper = h;
 		map = m;
-		sScale = Symbols.symbolScale[zoom]*factor;
-		tScale = Symbols.textScale[zoom]*factor;
+		sScale = Symbols.symbolScale[zoom] * factor;
+		tScale = Symbols.textScale[zoom] * factor;
 		if (map != null) {
 			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
@@ -46,17 +47,21 @@
 		}
 	}
-	
+
 	public static AttMap getAtts(Feature feature, Obj obj, int idx) {
 		HashMap<Integer, AttMap> objs = feature.objs.get(obj);
-		if (objs == null) return null;
-		else return objs.get(idx);
-	}
-	
+		if (objs == null)
+			return null;
+		else
+			return objs.get(idx);
+	}
+
 	public static Object getAttVal(Feature feature, Obj obj, int idx, Att att) {
 		AttMap atts = getAtts(feature, obj, idx);
-		if (atts == null) return S57val.nullVal(att);
+		if (atts == null)
+			return S57val.nullVal(att);
 		else {
 			AttItem item = atts.get(att);
-			if (item == null) return S57val.nullVal(att);
+			if (item == null)
+				return S57val.nullVal(att);
 			return item.val;
 		}
@@ -73,5 +78,5 @@
 		}
 	}
-	
+
 	private static Rectangle symbolSize(Symbol symbol) {
 		Symbol ssymb = symbol;
@@ -82,5 +87,5 @@
 				}
 				if (item.type == Prim.SYMB) {
-					ssymb = ((SubSymbol)item.params).instr;
+					ssymb = ((SubSymbol) item.params).instr;
 					break;
 				}
@@ -90,4 +95,8 @@
 		}
 		return null;
+	}
+
+	private double mile(Feature feature) {
+		return Math.pow(2, zoom) * 256 / (21600 * Math.abs(Math.cos(feature.centre.lat)));
 	}
 	
@@ -133,7 +142,7 @@
 					if (first) {
 						curr = succ = next;
-						gap  = (space > 0);
-						scount  = ratio;
-						symbol  = prisymb;
+						gap = (space > 0);
+						scount = ratio;
+						symbol = prisymb;
 						len = gap ? psize * space * 0.5 : psize;
 						first = false;
@@ -156,8 +165,8 @@
 							}
 							if (!gap) {
-								Symbols.drawSymbol(g2, symbol, sScale, curr.getX(), curr.getY(),
-										new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.atan2((succ.getY() - curr.getY()), (succ.getX() - curr.getX())) + Math.toRadians(90))), null);
-							}
-							if (space > 0) gap = !gap;
+								Symbols.drawSymbol(g2, symbol, sScale, curr.getX(), curr.getY(), new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.atan2((succ.getY() - curr.getY()), (succ.getX() - curr.getX())) + Math.toRadians(90))), null);
+							}
+							if (space > 0)
+								gap = !gap;
 							curr = succ;
 							len = gap ? (psize * space) : (--scount == 0) ? ssize : psize;
@@ -175,5 +184,5 @@
 	}
 
-	public static void lineVector (Feature feature, LineStyle style) {
+	public static void lineVector(Feature feature, LineStyle style) {
 		Path2D.Double p = new Path2D.Double();
 		p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
@@ -220,6 +229,6 @@
 		}
 	}
-	
-	public static void labelText (Feature feature, String str, Font font, Color colour, Delta delta) {
+
+	public static void labelText(Feature feature, String str, Font font, Color colour, Delta delta) {
 		Symbol label = new Symbol();
 		label.add(new Instr(Prim.TEXT, new Caption(str, font, colour, (delta == null) ? new Delta(Handle.CC, null) : delta)));
@@ -227,7 +236,74 @@
 		Symbols.drawSymbol(g2, label, tScale, point.getX(), point.getY(), null, null);
 	}
-	
-	public static void lineText (Feature feature, String str, Font font, Color colour, double offset, double dy) {
-		
+
+	public static void lineText(Feature feature, String str, Font font, Color colour, double offset, double dy) {
+		Area area;
+		switch (feature.flag) {
+		case LINE:
+			Edge edge = map.edges.get(feature.refs);
+			area = map.new Area();
+			area.add(map.new Bound(map.new Side(edge, true), true));
+			break;
+		case AREA:
+			area = map.areas.get(feature.refs);
+			break;
+		default:
+			return;
+		}
+//		Rectangle prect = symbolSize(prisymb);
+		if (!str.isEmpty()) {
+			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+	    FontRenderContext frc = g2.getFontRenderContext();
+	    GlyphVector gv = font.deriveFont((float)(font.getSize()*tScale)).createGlyphVector(frc, str);
+//			double psize = Math.abs(prect.getX());
+			Point2D prev = new Point2D.Double();
+			Point2D next = new Point2D.Double();
+			Point2D curr = new Point2D.Double();
+			Point2D succ = new Point2D.Double();
+			boolean gap = true;
+			boolean piv = false;
+			double len = 0;
+			double angle = 0;
+			for (Bound bound : area) {
+				BoundIterator bit = map.new BoundIterator(bound);
+				boolean first = true;
+				while (bit.hasNext()) {
+					prev = next;
+					next = helper.getPoint(bit.next());
+					angle = Math.atan2(next.getY() - prev.getY(), next.getX() - prev.getX());
+					piv = true;
+					if (first) {
+						curr = succ = next;
+//						gap = (space > 0);
+//						len = gap ? psize * space * 0.5 : psize;
+						first = false;
+					} else {
+						while (curr.distance(next) >= len) {
+							if (piv) {
+								double rem = len;
+								double s = prev.distance(next);
+								double p = curr.distance(prev);
+								if ((s > 0) && (p > 0)) {
+									double n = curr.distance(next);
+									double theta = Math.acos((s * s + p * p - n * n) / 2 / s / p);
+									double phi = Math.asin(p / len * Math.sin(theta));
+									rem = len * Math.sin(Math.PI - theta - phi) / Math.sin(theta);
+								}
+								succ = new Point2D.Double(prev.getX() + (rem * Math.cos(angle)), prev.getY() + (rem * Math.sin(angle)));
+								piv = false;
+							} else {
+								succ = new Point2D.Double(curr.getX() + (len * Math.cos(angle)), curr.getY() + (len * Math.sin(angle)));
+							}
+							if (!gap) {
+//								Symbols.drawSymbol(g2, symbol, sScale, curr.getX(), curr.getY(), new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.atan2((succ.getY() - curr.getY()), (succ.getX() - curr.getX())) + Math.toRadians(90))), null);
+							}
+							gap = false;
+							curr = succ;
+//							len = psize;
+						}
+					}
+				}
+			}
+		}
 	}
 }
Index: /applications/editors/josm/plugins/smed2/src/seamap/SeaMap.java
===================================================================
--- /applications/editors/josm/plugins/smed2/src/seamap/SeaMap.java	(revision 29825)
+++ /applications/editors/josm/plugins/smed2/src/seamap/SeaMap.java	(revision 29826)
@@ -163,5 +163,6 @@
 		public AttMap atts;
 		public ObjMap objs;
-		public long area;
+		public double area;
+		public double length;
 		public Snode centre;
 
@@ -173,4 +174,5 @@
 			objs = new ObjMap();
 			area = 0;
+			length = 0;
 			centre = new Snode();
 		}
@@ -377,4 +379,6 @@
 				node.flg = Nflag.ISOL;
 			}
+			feature.length = 0;
+			feature.area = 0;
 			break;
 		case LINE:
@@ -382,12 +386,18 @@
 			nodes.get(edge.first).flg = Nflag.CONN;
 			nodes.get(edge.last).flg = Nflag.CONN;
+			Bound ebound = (new Bound(new Side(edge, edge.forward), true));
+			feature.length = calcLength(ebound);
 			if (edge.first == edge.last) {
 				feature.flag = Fflag.AREA;
 				Area area = new Area();
-				area.add(new Bound(new Side(edge, edge.forward), true));
+				area.add(ebound);
+				feature.area = calcArea(ebound);
 				areas.put(id, area);
+			} else {
+				feature.area = 0;
 			}
 			break;
 		case AREA:
+			Bound bound = null;
 			Area area = new Area();
 			ArrayList<Long> role = outers;
@@ -397,5 +407,5 @@
 					long node1 = edge.first;
 					long node2 = edge.last;
-					Bound bound = new Bound(new Side(edge, edge.forward), (role == outers));
+					bound = new Bound(new Side(edge, edge.forward), (role == outers));
 					if (node1 != node2) {
 						for (ListIterator<Long> it = role.listIterator(0); it.hasNext();) {
@@ -417,4 +427,6 @@
 				}
 				if (role == outers) {
+					feature.length = calcLength(bound);
+					feature.area = calcArea(bound);
 					role = inners;
 				} else {
@@ -435,5 +447,5 @@
 	}
 
-	public double signedArea(Bound bound) {
+	double signedArea(Bound bound) {
 		Snode node;
 		double lat, lon, llon, llat;
@@ -449,5 +461,5 @@
 			sigma += (lon * Math.sin(llat)) - (llon * Math.sin(lat));
 		}
-		return sigma;
+		return sigma / 2.0;
 	}
 
@@ -457,5 +469,27 @@
 
 	public double calcArea(Bound bound) {
-		return Math.abs(signedArea(bound)) * 3444 * 3444 / 2.0;
+		return Math.abs(signedArea(bound)) * 3444 * 3444;
+	}
+
+	public double calcLength(Bound bound) {
+		Snode node;
+		double lat, lon, llon, llat;
+		lat = lon = llon = llat = 0;
+		double sigma = 0;
+		BoundIterator it = new BoundIterator(bound);
+		if (it.hasNext()) {
+			node = it.next();
+			lat = node.lat;
+			lon = node.lon;
+			while (it.hasNext()) {
+				llon = lon;
+				llat = lat;
+				node = it.next();
+				lat = node.lat;
+				lon = node.lon;
+				sigma += Math.acos(Math.sin(lat) * Math.sin(llat) + Math.cos(lat) * Math.cos(llat) * Math.cos(llon - lon));
+			}
+		}
+		return sigma * 3444;
 	}
 
