Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 880)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 885)
@@ -48,17 +48,11 @@
 
 	protected boolean isZoomOk(ElemStyle e) {
+		if (!zoomLevelDisplay) /* show everything if the user wishes so */
+			return true;
+
 		double circum = Main.map.mapView.getScale()*100*Main.proj.scaleFactor()*40041455; // circumference of the earth in meter
 
-		/* show everything if the user wishes so */
-		if (!zoomLevelDisplay) {
-			return true;
-		}
-
-		if (e == null) {
-			/* the default for things that don't have a rule (show, if scale is smaller than 1500m) */
-			if (circum < 1500)
-				return true;
-			return false;
-		}
+		if(e == null) /* the default for things that don't have a rule (show, if scale is smaller than 1500m) */
+			return (circum < 1500);
 
 		// formula to calculate a map scale: natural size / map size = scale
@@ -67,11 +61,5 @@
 		// so the exact "correcting value" below depends only on the screen size and resolution
 		// XXX - do we need a Preference setting for this (if things vary widely)?
-		/*System.out.println(
-		"Circum: " + circum +
-		" max: " + e.getMaxScale() + "(" + e.getMaxScale()/22 + ")" +
-		" min:" + e.getMinScale() + "(" + e.getMinScale()/22 + ")");*/
-		if(circum>=e.getMaxScale() / 22 || circum<e.getMinScale() / 22)
-			return false;
-		return true;
+		return !(circum >= e.maxScale / 22 || circum < e.minScale / 22);
 	}
 
@@ -83,14 +71,8 @@
 	 */
 	public void visit(Node n) {
-		ElemStyle nodeStyle = MapPaintStyles.getStyle(n);
-		if (nodeStyle!=null) {
-			if (nodeStyle instanceof IconElemStyle) {
-				if (isZoomOk(nodeStyle)) {
-					drawNode(n, ((IconElemStyle)nodeStyle).getIcon(), ((IconElemStyle)nodeStyle).doAnnotate());
-				}
-			} else {
-				// throw some sort of exception
-			}
-		} else {
+		IconElemStyle nodeStyle = MapPaintStyles.getStyles().get(n);
+		if (nodeStyle != null && isZoomOk(nodeStyle))
+			drawNode(n, nodeStyle.icon, nodeStyle.annotate);
+		else {
 			if (n.selected)
 				drawNode(n, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
@@ -113,27 +95,24 @@
 		 && (!showRelevantDirectionsOnly || w.hasDirectionKeys)));
 
-		Color colour = untaggedColor;
-		Color areacolour = untaggedColor;
+		Color color = untaggedColor;
+		Color areacolor = untaggedColor;
 		int width = defaultSegmentWidth;
 		int realWidth = 0; //the real width of the element in meters
 		boolean dashed = false;
 		boolean area = false;
-		ElemStyle wayStyle = MapPaintStyles.getStyle(w);
-
-		if(!isZoomOk(wayStyle)) {
+		ElemStyle wayStyle = MapPaintStyles.getStyles().get(w);
+
+		if(!isZoomOk(wayStyle))
 			return;
-		}
-
+
+		LineElemStyle l = null;
 		if(wayStyle!=null)
 		{
-			LineElemStyle l = null;
 			if(wayStyle instanceof LineElemStyle)
-			{
 				l = (LineElemStyle)wayStyle;
-			}
 			else if (wayStyle instanceof AreaElemStyle)
 			{
-				areacolour = ((AreaElemStyle)wayStyle).colour;
-				colour = areacolour;
+				areacolor = ((AreaElemStyle)wayStyle).color;
+				color = areacolor;
 				l = ((AreaElemStyle)wayStyle).line;
 				area = true;
@@ -141,5 +120,5 @@
 			if(l != null)
 			{
-				colour = l.colour;
+				color = l.color;
 				width = l.width;
 				realWidth = l.realWidth;
@@ -149,26 +128,67 @@
 
 		if (area && fillAreas)
-			drawWayAsArea(w, areacolour);
-		int orderNumber = 0;
-
-		Node lastN = null;
-		for (Node n : w.nodes) {
-			if (lastN == null) {
+			drawWayAsArea(w, areacolor);
+		if (realWidth > 0 && useRealWidth && !showDirection)
+		{
+			int tmpWidth = (int) (100 /  (float) (circum / realWidth));
+			if (tmpWidth > width) width = tmpWidth;
+		}
+
+		Node lastN;
+		if(l != null && l.overlays != null)
+		{
+			for(LineElemStyle s : l.overlays)
+			{
+				if(!s.over)
+				{
+					lastN = null;
+					for(Node n : w.nodes)
+					{
+						if(lastN != null)
+							drawSeg(lastN, n, s.color != null ? s.color : color, false, s.getWidth(width), s.dashed);
+						lastN = n;
+					}
+				}
+			}
+		}
+
+		lastN = null;
+		for(Node n : w.nodes)
+		{
+			if(lastN != null)
+				drawSeg(lastN, n, w.selected ? selectedColor : color, showDirection, width, dashed);
+			lastN = n;
+		}
+
+		if(l != null && l.overlays != null)
+		{
+			for(LineElemStyle s : l.overlays)
+			{
+				if(s.over)
+				{
+					lastN = null;
+					for(Node n : w.nodes)
+					{
+						if(lastN != null)
+							drawSeg(lastN, n, s.color != null ? s.color : color, false, s.getWidth(width), s.dashed);
+						lastN = n;
+					}
+				}
+			}
+		}
+
+		if(showOrderNumber)
+		{
+			int orderNumber = 0;
+			lastN = null;
+			for(Node n : w.nodes)
+			{
+				if(lastN != null)
+				{
+					orderNumber++;
+					drawOrderNumber(lastN, n, orderNumber);
+				}
 				lastN = n;
-				continue;
-			}
-			orderNumber++;
-
-			if (realWidth > 0 && useRealWidth && !showDirection)
-			{
-				int tmpWidth = (int) (100 /  (float) (circum / realWidth));
-				if (tmpWidth > width) width = tmpWidth;
-			}
-			drawSeg(lastN, n, w.selected ? selectedColor : colour, showDirection, width, dashed);
-
-			if (showOrderNumber)
-				drawOrderNumber(lastN, n, orderNumber);
-
-			lastN = n;
+			}
 		}
 	}
@@ -179,5 +199,5 @@
 
 	// This assumes that all segments are aligned in the same direction!
-	protected void drawWayAsArea(Way w, Color colour)
+	protected void drawWayAsArea(Way w, Color color)
 	{
 		Polygon polygon = new Polygon();
@@ -189,5 +209,5 @@
 		}
 
-		Color mycolor = w.selected ? selectedColor : colour;
+		Color mycolor = w.selected ? selectedColor : color;
 		// set the opacity (alpha) level of the filled polygon
 		g.setColor(new Color( mycolor.getRed(), mycolor.getGreen(), mycolor.getBlue(), fillAlpha));
@@ -299,5 +319,5 @@
 
 		for (final OsmPrimitive osm : data.ways)
-			if (!osm.incomplete && !osm.deleted && MapPaintStyles.isArea(osm))
+			if (!osm.incomplete && !osm.deleted && MapPaintStyles.getStyles().isArea((Way)osm))
 				osm.visit(this);
 			else if (!osm.deleted && !osm.incomplete)
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/AreaElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/AreaElemStyle.java	(revision 880)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/AreaElemStyle.java	(revision 885)
@@ -4,9 +4,10 @@
 public class AreaElemStyle extends ElemStyle
 {
-	public Color colour;
+	public Color color;
 	public LineElemStyle line = null;
 
-	public AreaElemStyle (Color colour, long maxScale, long minScale) {
-		this.colour = colour;
+	public AreaElemStyle (AreaElemStyle a, long maxScale, long minScale) {
+		this.color = a.color;
+		this.priority = a.priority;
 		this.maxScale = maxScale;
 		this.minScale = minScale;
@@ -15,5 +16,6 @@
 	public AreaElemStyle(AreaElemStyle a, LineElemStyle l)
 	{
-		this.colour = a.colour;
+		this.color = a.color;
+		this.priority = a.priority;
 		this.maxScale = a.maxScale;
 		this.minScale = a.minScale;
@@ -21,6 +23,10 @@
 	}
 
-	@Override public String toString() {
-		return "AreaElemStyle:   colour=" + colour;
+	public AreaElemStyle() { init(); }
+
+	public void init()
+	{
+		color = null;
+		priority = 0;
 	}
 }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java	(revision 880)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java	(revision 885)
@@ -4,13 +4,8 @@
 {
 	// zoom range to display the feature
-	protected long minScale;
-	protected long maxScale;
+	public long minScale;
+	public long maxScale;
 
-	public long getMinScale() {
-		return minScale;
-	}
-	public long getMaxScale() {
-		return maxScale;
-	}
+	public int priority;
 }
 
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyleHandler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyleHandler.java	(revision 880)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyleHandler.java	(revision 885)
@@ -2,33 +2,44 @@
 
 import java.awt.Color;
-import java.awt.Toolkit;
-import java.io.File;
-import java.net.URL;
-
-import javax.swing.ImageIcon;
 
 import org.openstreetmap.josm.tools.ColorHelper;
-import org.openstreetmap.josm.Main;
 import org.xml.sax.Attributes;
 import org.xml.sax.helpers.DefaultHandler;
 
+import org.openstreetmap.josm.Main;
+
 public class ElemStyleHandler extends DefaultHandler
 {
-	boolean inDoc, inRule, inCondition, inElemStyle, inLine, inIcon, inArea, inScaleMax, inScaleMin;
-	String curKey = null;
-	String curValue = null;
-	String curBoolean = null;
-	int curLineWidth = -1;
-	int curLineRealWidth = 0;
-	boolean curLineDashed = false;
-	Color curLineColour = null;
-	Color curAreaColour = null;
-	ImageIcon curIcon = null;
-	boolean curIconAnnotate = true;
-	long curScaleMax = 1000000000;
-	long curScaleMin = 0;
+	boolean inDoc, inRule, inCondition, inElemStyle, inLine, inLineMod, inIcon, inArea, inScaleMax, inScaleMin;
+	boolean hadLine, hadLineMod, hadIcon, hadArea;
+	ElemStyles styles;
+	RuleElem rule = new RuleElem();
+
+	class RuleElem {
+		String key;
+		String value;
+		String boolValue;
+		long scaleMax;
+		long scaleMin;
+		LineElemStyle line = new LineElemStyle();
+		LineElemStyle linemod = new LineElemStyle();
+		AreaElemStyle area = new AreaElemStyle();
+		IconElemStyle icon = new IconElemStyle();
+		public void init()
+		{
+			key = value = boolValue = null;
+			scaleMax = 1000000000;
+			scaleMin = 0;
+			line.init();
+			linemod.init();
+			area.init();
+			icon.init();
+		}
+	};
 
 	public ElemStyleHandler() {
 		inDoc=inRule=inCondition=inElemStyle=inLine=inIcon=inArea=false;
+		rule.init();
+		styles = MapPaintStyles.getStyles();
 	}
 
@@ -54,81 +65,103 @@
 	}
 
-	@Override public void startElement(String uri,String name, String qName, 
-			Attributes atts) {
-		if (inDoc==true)	{
-			if (qName.equals("rule")) {
+	@Override public void startElement(String uri,String name, String qName, Attributes atts) {
+		if (inDoc==true)
+		{
+			if (qName.equals("rule"))
 				inRule=true;
-			}
-			else if (qName.equals("condition") && inRule) {
+			else if (qName.equals("scale_max"))
+				inScaleMax = true;
+			else if (qName.equals("scale_min"))
+				inScaleMin = true;
+			else if (qName.equals("condition") && inRule)
+			{
 				inCondition=true;
-				for (int count=0; count<atts.getLength(); count++) {
+				for (int count=0; count<atts.getLength(); count++)
+				{
 					if(atts.getQName(count).equals("k"))
+						rule.key = atts.getValue(count);
+					else if(atts.getQName(count).equals("v"))
+						rule.value = atts.getValue(count);
+					else if(atts.getQName(count).equals("b"))
+						rule.boolValue = atts.getValue(count);
+				}
+			}
+			else if (qName.equals("line"))
+			{
+				hadLine = inLine = true;
+				for (int count=0; count<atts.getLength(); count++)
+				{
+					if(atts.getQName(count).equals("width"))
+						rule.line.width = Integer.parseInt(atts.getValue(count));
+					else if (atts.getQName(count).equals("colour"))
+						rule.line.color=convertColor(atts.getValue(count));
+					else if (atts.getQName(count).equals("realwidth"))
+						rule.line.realWidth=Integer.parseInt(atts.getValue(count));
+					else if (atts.getQName(count).equals("dashed"))
+						rule.line.dashed=Boolean.parseBoolean(atts.getValue(count));
+					else if(atts.getQName(count).equals("priority"))
+						rule.line.priority = Integer.parseInt(atts.getValue(count));
+				}
+			}
+			else if (qName.equals("linemod"))
+			{
+				hadLineMod = inLine = true;
+				for (int count=0; count<atts.getLength(); count++)
+				{
+					if(atts.getQName(count).equals("width"))
 					{
-						curKey = atts.getValue(count);
-						curBoolean = null;
-						curValue = null;
+						String val = atts.getValue(count);
+						if(val.startsWith("+"))
+						{
+							rule.line.width = Integer.parseInt(val.substring(1));
+							rule.line.widthMode = LineElemStyle.WidthMode.OFFSET;
+						}
+						else if(val.startsWith("-"))
+						{
+							rule.line.width = Integer.parseInt(val);
+							rule.line.widthMode = LineElemStyle.WidthMode.OFFSET;
+						}
+						else if(val.endsWith("%"))
+						{
+							rule.line.width = Integer.parseInt(val.substring(0, val.length()-1));
+							rule.line.widthMode = LineElemStyle.WidthMode.PERCENT;
+						}
+						else
+							rule.line.width = Integer.parseInt(val);
 					}
-					else if(atts.getQName(count).equals("v"))
-						curValue = atts.getValue(count);
-					else if(atts.getQName(count).equals("b"))
-						curBoolean = atts.getValue(count);
-				}
-			} else if (qName.equals("line")) {
-				inLine = true;
-				for (int count=0; count<atts.getLength(); count++) {
-					if(atts.getQName(count).equals("width"))
-						curLineWidth = Integer.parseInt(atts.getValue(count));
 					else if (atts.getQName(count).equals("colour"))
-						curLineColour=convertColor(atts.getValue(count));
+						rule.line.color=convertColor(atts.getValue(count));
 					else if (atts.getQName(count).equals("realwidth"))
-						curLineRealWidth=Integer.parseInt(atts.getValue(count));
+						rule.line.realWidth=Integer.parseInt(atts.getValue(count));
 					else if (atts.getQName(count).equals("dashed"))
-						curLineDashed=Boolean.parseBoolean(atts.getValue(count));
-				}
-			} else if (qName.equals("scale_max")) {
-				inScaleMax = true;
-			} else if (qName.equals("scale_min")) {
-				inScaleMin = true;
-			} else if (qName.equals("icon")) {
-				inIcon = true;
-				for (int count=0; count<atts.getLength(); count++) {
-					if (atts.getQName(count).equals("src")) {
-						if(!MapPaintStyles.isInternal())
-						{
-							String imageFile = MapPaintStyles.getImageDir()+atts.getValue(count); 
-							File f = new File(imageFile);
-							if (f.exists()) {
-								//open icon from user directory
-								curIcon = new ImageIcon(imageFile);
-								continue;
-							}
-						}
-						try {
-							URL path = getClass().getResource(MapPaintStyles.getInternalImageDir()+atts.getValue(count));
-							if (path == null) {
-								/* icon not found, using default */
-								System.out.println("Mappaint: Icon " + atts.getValue(count) + " not found, using default icon");
-								path = getClass().getResource(MapPaintStyles.getInternalImageDir()+"misc/no_icon.png");
-								curIcon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(path));
-							} else {
-								curIcon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(path));
-							}
-						}
-						catch (Exception e){
-							URL path = getClass().getResource(MapPaintStyles.getInternalImageDir()+"incomming/amenity.png");
-							curIcon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(path));
-						}
-					} else if (atts.getQName(count).equals("annotate")) {
-						curIconAnnotate = Boolean.parseBoolean (atts.getValue(count));
-					}
+						rule.line.dashed=Boolean.parseBoolean(atts.getValue(count));
+					else if(atts.getQName(count).equals("priority"))
+						rule.line.priority = Integer.parseInt(atts.getValue(count));
+					else if(atts.getQName(count).equals("mode"))
+						rule.line.over = !atts.getValue(count).equals("under");
+				}
+			}
+			else if (qName.equals("icon"))
+			{
+				hadIcon = inIcon = true;
+				for (int count=0; count<atts.getLength(); count++)
+				{
+					if (atts.getQName(count).equals("src"))
+						rule.icon.icon = MapPaintStyles.getIcon(atts.getValue(count));
+					else if (atts.getQName(count).equals("annotate"))
+						rule.icon.annotate = Boolean.parseBoolean (atts.getValue(count));
+					else if(atts.getQName(count).equals("priority"))
+						rule.icon.priority = Integer.parseInt(atts.getValue(count));
 				}
 			}
 			else if (qName.equals("area"))
 			{
-				inArea = true;
+				hadArea = inArea = true;
 				for (int count=0; count<atts.getLength(); count++)
 				{
 					if (atts.getQName(count).equals("colour"))
-						curAreaColour=convertColor(atts.getValue(count));
+						rule.area.color=convertColor(atts.getValue(count));
+					else if(atts.getQName(count).equals("priority"))
+						rule.area.priority = Integer.parseInt(atts.getValue(count));
 				}
 			}
@@ -138,31 +171,21 @@
 	@Override public void endElement(String uri,String name, String qName)
 	{
-		if (inRule && qName.equals("rule")) {
-			ElemStyle newStyle;
+		if (inRule && qName.equals("rule"))
+		{
+			if(hadLine)
+				styles.add(rule.key, rule.value, rule.boolValue,
+				new LineElemStyle(rule.line, rule.scaleMax, rule.scaleMin));
+			if(hadLineMod)
+				styles.addModifier(rule.key, rule.value, rule.boolValue,
+				new LineElemStyle(rule.line, rule.scaleMax, rule.scaleMin));
+			if(hadIcon)
+				styles.add(rule.key, rule.value, rule.boolValue,
+				new IconElemStyle(rule.icon, rule.scaleMax, rule.scaleMin));
+			if(hadArea)
+				styles.add(rule.key, rule.value, rule.boolValue,
+				new AreaElemStyle(rule.area, rule.scaleMax, rule.scaleMin));
 			inRule = false;
-			if (curLineWidth != -1) {
-				newStyle = new LineElemStyle(curLineWidth, curLineRealWidth, curLineColour, 
-						curLineDashed, curScaleMax, curScaleMin);
-				MapPaintStyles.add(curKey, curValue, curBoolean, newStyle);
-				curLineWidth = -1;
-				curLineRealWidth= 0;
-				curLineDashed = false;
-				curLineColour = null;
-			}
-			
-			if (curIcon != null) {
-				newStyle = new IconElemStyle(curIcon, curIconAnnotate, curScaleMax, curScaleMin);
-				MapPaintStyles.add(curKey, curValue, curBoolean, newStyle);
-				curIcon = null;
-				curIconAnnotate = true;
-			}
-			if (curAreaColour != null) {
-				newStyle = new AreaElemStyle (curAreaColour, curScaleMax, curScaleMin);
-				MapPaintStyles.add(curKey, curValue, curBoolean, newStyle);
-				curAreaColour = null;
-			}
-			curScaleMax = 1000000000;
-			curScaleMin = 0;
-
+			hadLine = hadLineMod = hadIcon = hadArea = false;
+			rule.init();
 		}
 		else if (inCondition && qName.equals("condition"))
@@ -180,17 +203,10 @@
 	}
 
-	@Override public void characters(char ch[], int start, int length) {
-		if (inScaleMax == true) {
-			String content = new String(ch, start, length);
-			curScaleMax = Long.parseLong(content);
-		}
-		if (inScaleMin == true) {
-			String content = new String(ch, start, length);
-			curScaleMin = Long.parseLong(content);
-		}
+	@Override public void characters(char ch[], int start, int length)
+	{
+		if (inScaleMax == true)
+			rule.scaleMax = Long.parseLong(new String(ch, start, length));
+		else if (inScaleMin == true)
+			rule.scaleMin = Long.parseLong(new String(ch, start, length));
 	}
 }
-
-
-
-
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 880)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 885)
@@ -1,105 +1,159 @@
 package org.openstreetmap.josm.gui.mappaint;
 
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Iterator;
 
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.OsmUtils;
+import org.openstreetmap.josm.data.osm.Way;
 
 public class ElemStyles
 {
-	private HashMap<String, ElemStyle> styles;
+	private HashMap<String, IconElemStyle> icons;
+	private HashMap<String, LineElemStyle> lines;
+	private HashMap<String, AreaElemStyle> areas;
+	private HashMap<String, LineElemStyle> modifiers;
 
 	public ElemStyles()
 	{
-		styles = new HashMap<String, ElemStyle>();
+		icons = new HashMap<String, IconElemStyle>();
+		lines = new HashMap<String, LineElemStyle>();
+		modifiers = new HashMap<String, LineElemStyle>();
+		areas = new HashMap<String, AreaElemStyle>();
 	}
 
-	public void add(String k, String v, String b, ElemStyle style)
+	private String getKey(String k, String v, String b)
 	{
-		ElemStyle  old_style;
-		String key;
-
-		/* unfortunately, there don't seem to be an efficient way to */
-		/* find out, if a given OsmPrimitive is an area or not, */
-		/* so distinguish only between way and node here - for now */
-		if (style instanceof AreaElemStyle)
-			key = "w";
-		else if (style instanceof LineElemStyle)
-			key = "w";
-		else if (style instanceof IconElemStyle)
-			key = "n";
+		if(v != null)
+			return "n" + k + "=" + v;
+		else if(b != null)
+			return "b" + k  + "=" + OsmUtils.getNamedOsmBoolean(b);
 		else
-			key = "";
-
-		if(v != null)
-			key += "n" + k + "=" + v;
-		else if(b != null)
-			key += "b" + k  + "=" + OsmUtils.getNamedOsmBoolean(b);
-		else
-			key += "x" + k;
-
-		/* avoid duplicates - for now */
-		old_style = styles.get(key);
-		if (old_style == null) {
-			/* new key/value, insert */
-			styles.put(key, style);
-		} else {
-			if (style.getMaxScale() < old_style.getMaxScale()) {
-				/* existing larger scale key/value, replace */
-				styles.remove(old_style);
-				styles.put(key, style);
-			}
-		}
+			return "x" + k;
 	}
 
-	public ElemStyle get(OsmPrimitive p, Boolean area)
+	public void add(String k, String v, String b, LineElemStyle style)
 	{
-		if (p.keys!=null) {
-			String classname;
-			String kv = null;
+		lines.put(getKey(k,v,b), style);
+	}
 
-			if (p instanceof org.openstreetmap.josm.data.osm.Node) {
-				if(area)
-					return null;
-				classname = "n";
-			} else {
-				classname = "w";
-			}
-			Iterator<String> iterator = p.keys.keySet().iterator();
-			while (iterator.hasNext())
+	public void addModifier(String k, String v, String b, LineElemStyle style)
+	{
+		modifiers.put(getKey(k,v,b), style);
+	}
+
+	public void add(String k, String v, String b, AreaElemStyle style)
+	{
+		areas.put(getKey(k,v,b), style);
+	}
+
+	public void add(String k, String v, String b, IconElemStyle style)
+	{
+		icons.put(getKey(k,v,b), style);
+	}
+
+	public IconElemStyle get(Node n)
+	{
+		IconElemStyle ret = null;
+		if(n.keys != null)
+		{
+			Iterator<String> iterator = n.keys.keySet().iterator();
+			while(iterator.hasNext())
 			{
 				String key = iterator.next();
-				ElemStyle style = null;
-				kv = classname + "n" + key + "=" + p.keys.get(key);
-				if (styles.containsKey(kv))
+				String val = n.keys.get(key);
+				IconElemStyle style;
+				if((style = icons.get("n" + key + "=" + val)) != null)
 				{
-					style = styles.get(kv);
-					if(area == style instanceof AreaElemStyle)
-						return style;
+					if(ret == null || style.priority > ret.priority)
+						ret = style;
 				}
-				kv = classname + "b" + key + "=" + OsmUtils.getNamedOsmBoolean(p.keys.get(key));
-				if (styles.containsKey(kv))
+				if((style = icons.get("n" + key + "=" + OsmUtils.getNamedOsmBoolean(val))) != null)
 				{
-					style = styles.get(kv);
-					if(area == style instanceof AreaElemStyle)
-						return style;
+					if(ret == null || style.priority > ret.priority)
+						ret = style;
 				}
-				kv = classname + "x" + key;
-				if (styles.containsKey(kv))
+				if((style = icons.get("x" + key)) != null)
 				{
-					style = styles.get(kv);
-					if(area == style instanceof AreaElemStyle)
-						return style;
+					if(ret == null || style.priority > ret.priority)
+						ret = style;
 				}
 			}
 		}
-
-		return null;
+		return ret;
 	}
 
-	public boolean isArea(OsmPrimitive p)
+	public ElemStyle get(Way w)
 	{
-		return get(p, true) instanceof AreaElemStyle;
+		AreaElemStyle retArea = null;
+		LineElemStyle retLine = null;
+		List<LineElemStyle> over = new LinkedList<LineElemStyle>();
+		if(w.keys != null)
+		{
+			Iterator<String> iterator = w.keys.keySet().iterator();
+			while(iterator.hasNext())
+			{
+				String key = iterator.next();
+				String val = w.keys.get(key);
+				AreaElemStyle styleArea;
+				LineElemStyle styleLine;
+				String idx = "n" + key + "=" + val;
+				if((styleArea = areas.get(idx)) != null && (retArea == null || styleArea.priority > retArea.priority))
+					retArea = styleArea;
+				if((styleLine = lines.get(idx)) != null && (retLine == null || styleLine.priority > retLine.priority))
+					retLine = styleLine;
+				if((styleLine = modifiers.get(idx)) != null)
+					over.add(styleLine);
+				idx = "b" + key + "=" + OsmUtils.getNamedOsmBoolean(val);
+				if((styleArea = areas.get(idx)) != null && (retArea == null || styleArea.priority > retArea.priority))
+					retArea = styleArea;
+				if((styleLine = lines.get(idx)) != null && (retLine == null || styleLine.priority > retLine.priority))
+					retLine = styleLine;
+				if((styleLine = modifiers.get(idx)) != null)
+					over.add(styleLine);
+				idx = "x" + key;
+				if((styleArea = areas.get(idx)) != null && (retArea == null || styleArea.priority > retArea.priority))
+					retArea = styleArea;
+				if((styleLine = lines.get(idx)) != null && (retLine == null || styleLine.priority > retLine.priority))
+					retLine = styleLine;
+				if((styleLine = modifiers.get(idx)) != null)
+					over.add(styleLine);
+			}
+		}
+		if(over.size() != 0 && retLine != null)
+		{
+			Collections.sort(over);
+			retLine = new LineElemStyle(retLine, over);
+		}
+		if(retArea != null)
+		{
+			if(retLine != null)
+				return new AreaElemStyle(retArea, retLine);
+			else
+				return retArea;
+		}
+		return retLine;
+	}
+
+	public boolean isArea(Way w)
+	{
+		if(w.keys != null)
+		{
+			Iterator<String> iterator = w.keys.keySet().iterator();
+			while(iterator.hasNext())
+			{
+				String key = iterator.next();
+				String val = w.keys.get(key);
+				if(areas.containsKey("n" + key + "=" + val)
+				|| areas.containsKey("n" + key + "=" + OsmUtils.getNamedOsmBoolean(val))
+				|| areas.containsKey("x" + key))
+					return true;
+			}
+		}
+		return false;
 	}
 }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/IconElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/IconElemStyle.java	(revision 880)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/IconElemStyle.java	(revision 885)
@@ -4,25 +4,21 @@
 public class IconElemStyle extends ElemStyle
 {
-	ImageIcon icon;
-	boolean annotate;
+	public ImageIcon icon;
+	public boolean annotate;
 
-	public IconElemStyle (ImageIcon icon, boolean annotate, long maxScale, long minScale) {
-		this.icon=icon;
-		this.annotate=annotate;
+	public IconElemStyle (IconElemStyle i, long maxScale, long minScale) {
+		this.icon = i.icon;
+		this.annotate = i.annotate;
+		this.priority = i.priority;
 		this.maxScale = maxScale;
 		this.minScale = minScale;
-	}	
-	
-	public ImageIcon getIcon() {
-		return icon;
 	}
+	public IconElemStyle() { init(); }
 
-	public boolean doAnnotate() {
-		return annotate;
-	}
-
-	@Override public String toString()
+	public void init()
 	{
-		return "IconElemStyle:  icon= " + icon +  " annotate=" + annotate;
+		icon = null;
+		priority = 0;
+		annotate = true;
 	}
 }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 880)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 885)
@@ -1,23 +1,89 @@
 package org.openstreetmap.josm.gui.mappaint;
+
 import java.awt.Color;
+import java.util.LinkedList;
+import java.util.List;
 
-public class LineElemStyle extends ElemStyle
+public class LineElemStyle extends ElemStyle implements Comparable<LineElemStyle>
 {
 	public int width;
-	public int realWidth = 0; //the real width of this line in meter
-	public Color colour;
-	public boolean dashed = false;
+	public int realWidth; //the real width of this line in meter
+	public Color color;
+	public boolean dashed;
 
-	public LineElemStyle (int width, int realWidth, Color colour, boolean dashed, long maxScale, long minScale) {
-		this.width = width;
-		this.realWidth = realWidth;
-		this.colour = colour;
-		this.dashed = dashed;
+	public boolean over;
+	public enum WidthMode { ABSOLUTE, PERCENT, OFFSET };
+	public WidthMode widthMode;
+
+	public List<LineElemStyle> overlays;
+
+	public LineElemStyle(LineElemStyle s, long maxScale, long minScale) {
+		this.width = s.width;
+		this.realWidth = s.realWidth;
+		this.color = s.color;
+		this.dashed = s.dashed;
+		this.over = s.over;
+		this.widthMode = s.widthMode;
+
+		this.priority = s.priority;
 		this.maxScale = maxScale;
 		this.minScale = minScale;
 	}
 
-	@Override public String toString() {
-		return "LineElemStyle:  width= " + width + "realWidth= " + realWidth +  " colour=" + colour + " dashed=" + dashed;
+	public LineElemStyle(LineElemStyle s, List<LineElemStyle> overlays) {
+		this.width = s.width;
+		this.realWidth = s.realWidth;
+		this.color = s.color;
+		this.dashed = s.dashed;
+		this.over = s.over;
+		this.widthMode = s.widthMode;
+
+		this.priority = s.priority;
+		this.maxScale = s.maxScale;
+		this.minScale = s.minScale;
+
+		this.overlays = overlays;
+	}
+
+	public LineElemStyle() { init(); }
+
+	public void init()
+	{
+		width = 1;
+		realWidth = 0;
+		dashed = false;
+		priority = 0;
+		color = null;
+		over = true; // only used for line modifications
+		widthMode = WidthMode.ABSOLUTE;
+		overlays = null;
+	};
+
+	// get width for overlays
+	public int getWidth(int ref)
+	{
+		int res;
+		if(widthMode == WidthMode.ABSOLUTE)
+			res = width;
+		else if(widthMode == WidthMode.OFFSET)
+			res = ref + width;
+		else
+		{
+			if(width < 0)
+				res = 0;
+			else
+				res = ref*width/100;
+		}
+		return res <= 0 ? 1 : res;
+	}
+
+	public int compareTo(LineElemStyle s)
+	{
+		if(s.priority != priority)
+			return s.priority > priority ? 1 : -1;
+		if(!over && s.over)
+			return -1;
+		// we have no idea how to order other objects :-)
+		return 0;
 	}
 }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 880)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 885)
@@ -1,4 +1,5 @@
 package org.openstreetmap.josm.gui.mappaint;
 
+import java.awt.Toolkit;
 import java.io.File;
 import java.io.FileReader;
@@ -6,4 +7,6 @@
 import java.util.HashMap;
 import java.util.Iterator;
+
+import javax.swing.ImageIcon;
 
 import org.openstreetmap.josm.Main;
@@ -22,47 +25,43 @@
 	private static ElemStyles styles = new ElemStyles();
 	
-	public static String getStyleDir(){
-		return styleDir;
+	public static ElemStyles getStyles()
+	{
+		return styles;
 	}
-	public static String getImageDir(){
-		return imageDir;
-	}
-	public static String getInternalImageDir(){
-		return internalImageDir;
-	}
-	public static Boolean isInternal(){
-		return isInternal;
-	}
-	public static void add(String k, String v, String b, ElemStyle style)
+
+	public static ImageIcon getIcon(String name)
 	{
-		styles.add(k, v, b, style);
-	}
-	public static ElemStyle getStyle(OsmPrimitive osm)
-	{
-		ElemStyle s = styles.get(osm, true);
-		if(s != null)
+		try {
+			if(isInternal)
+			{
+				String imageFile = imageDir+name;
+				File f = new File(imageFile);
+				if(f.exists())
+				{
+					//open icon from user directory
+					return new ImageIcon(imageFile);
+				}
+			}
+			URL path = Main.class.getResource(internalImageDir+name);
+			if(path == null)
+			{
+				System.out.println("Mappaint: Icon " + name + " not found, using default icon");
+				path = Main.class.getResource(internalImageDir+"misc/no_icon.png");
+			}
+			return new ImageIcon(Toolkit.getDefaultToolkit().createImage(path));
+		}
+		catch (Exception e)
 		{
-			ElemStyle l = styles.get(osm, false);
-			if(l != null && l instanceof LineElemStyle)
-			{
-				s = new AreaElemStyle((AreaElemStyle)s, (LineElemStyle)l);
-			}
+			URL path = Main.class.getResource(internalImageDir+"incomming/amenity.png");
+			return new ImageIcon(Toolkit.getDefaultToolkit().createImage(path));
 		}
-		else
-			s = styles.get(osm, false);
-		return s;
-	}
-	public static boolean isArea(OsmPrimitive osm)
-	{
-		return styles.isArea(osm);
 	}
 
 	public static void readFromPreferences() {
-
 		String styleName = Main.pref.get("mappaint.style", "standard");
 		// fallback to standard name for internal case, as we only have one internal style
 		String internalStyleName = "standard";
 		styleDir = Main.pref.get("mappaint.styledir", Main.pref.getPreferencesDir()+"plugins/mappaint/"+styleName+"/");
-		String elemStylesFile = getStyleDir()+"elemstyles.xml";
+		String elemStylesFile = styleDir+"elemstyles.xml";
 		imageDir = styleDir+"icons/";
 		internalImageDir = "/images/styles/"+internalStyleName+"/";
Index: trunk/src/org/openstreetmap/josm/tools/ColorHelper.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/ColorHelper.java	(revision 880)
+++ trunk/src/org/openstreetmap/josm/tools/ColorHelper.java	(revision 885)
@@ -12,5 +12,5 @@
 		if (html.length() > 0 && html.charAt(0) == '#')
 			html = html.substring(1);
-		if (html.length() != 6)
+		else if (html.length() != 6 && html.length() != 8)
 			return null;
 		try {
@@ -18,5 +18,6 @@
 					Integer.parseInt(html.substring(0,2),16),
 					Integer.parseInt(html.substring(2,4),16),
-					Integer.parseInt(html.substring(4,6),16));
+					Integer.parseInt(html.substring(4,6),16),
+					(html.length() == 8 ? Integer.parseInt(html.substring(6,8),16) : 255));
 		} catch (NumberFormatException e) {
 			return null;
