Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 3859)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 3860)
@@ -100,5 +100,5 @@
     }
 
-    public void drawWay(Way way, Color color, float width, float dashed[], float dashesOffset, Color dashedColor, boolean showDirection,
+    public void drawWay(Way way, Color color, BasicStroke line, BasicStroke dashes, Color dashedColor, boolean showDirection,
             boolean reversedDirection, boolean showHeadArrowOnly) {
 
@@ -156,30 +156,18 @@
             lastPoint = p;
         }
-        displaySegments(path, arrows, color, width, dashed, dashesOffset, dashedColor);
-    }
-
-    private void displaySegments(GeneralPath path, GeneralPath arrows, Color color, float width, float dashed[], float dashesOffset, Color dashedColor) {
+        displaySegments(path, arrows, color, line, dashes, dashedColor);
+    }
+
+    private void displaySegments(GeneralPath path, GeneralPath arrows, Color color, BasicStroke line, BasicStroke dashes, Color dashedColor) {
         g.setColor(inactive ? inactiveColor : color);
         if (useStrokes) {
-            if (dashed != null && dashed.length > 0) {
-                g.setStroke(new BasicStroke(width,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,0,dashed,dashesOffset));
-            } else {
-                g.setStroke(new BasicStroke(width,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
-            }
+            g.setStroke(line);
         }
         g.draw(path);
         g.draw(arrows);
 
-        if(!inactive && useStrokes && dashedColor != null) {
+        if(!inactive && useStrokes && dashes != null) {
             g.setColor(dashedColor);
-            if (dashed != null && dashed.length > 0) {
-                float[] dashedOffset = new float[dashed.length];
-                System.arraycopy(dashed, 0, dashedOffset, 1, dashed.length - 1);
-                dashedOffset[0] = dashed[dashed.length-1];
-                float offset = dashedOffset[0] + dashesOffset;
-                g.setStroke(new BasicStroke(width,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,0,dashedOffset, offset));
-            } else {
-                g.setStroke(new BasicStroke(width,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
-            }
+            g.setStroke(dashes);
             g.draw(path);
             g.draw(arrows);
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/Cascade.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/Cascade.java	(revision 3859)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/Cascade.java	(revision 3860)
@@ -19,4 +19,8 @@
     protected Map<String, Object> prop = new HashMap<String, Object>();
 
+    public <T> T get(String key, T def, Class<T> klass) {
+        return get(key, def, klass, false);
+    }
+    
     /**
      * Get value for the given key
@@ -24,8 +28,10 @@
      * @param def default value, can be null
      * @param klass the same as T
+     * @param suppressWarnings show or don't show a warning when some value is
+     *      found, but cannot be converted to the requested type
      * @return if a value with class klass has been mapped to key, returns this
      *      value, def otherwise
      */
-    public <T> T get(String key, T def, Class<T> klass) {
+    public <T> T get(String key, T def, Class<T> klass, boolean suppressWarnings) {
         if (def != null && !klass.isInstance(def))
             throw new IllegalArgumentException();
@@ -35,5 +41,7 @@
         T res = convertTo(o, klass);
         if (res == null) {
-            System.err.println(String.format("Warning: unable to convert property %s to type %s: found %s of type %s!", key, klass, o, o.getClass()));
+            if (!suppressWarnings) {
+                System.err.println(String.format("Warning: unable to convert property %s to type %s: found %s of type %s!", key, klass, o, o.getClass()));
+            }
             return def;
         } else
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 3859)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 3860)
@@ -193,4 +193,5 @@
         List<ElemStyle> sl = new ArrayList<ElemStyle>();
         MultiCascade mc = new MultiCascade();
+        Environment env = new Environment(osm, mc, null, null);
 
         for (StyleSource s : styleSources) {
@@ -203,9 +204,10 @@
             if ("*".equals(e.getKey()))
                 continue;
+            env.layer = e.getKey();
             Cascade c = e.getValue();
             if (osm instanceof Way) {
                 addIfNotNull(sl, AreaElemStyle.create(c));
-                addIfNotNull(sl, LineElemStyle.createLine(c));
-                addIfNotNull(sl, LineElemStyle.createCasing(c));
+                addIfNotNull(sl, LineElemStyle.createLine(env));
+                addIfNotNull(sl, LineElemStyle.createCasing(env));
             } else if (osm instanceof Node) {
                 addIfNotNull(sl, NodeElemStyle.create(c));
@@ -213,6 +215,6 @@
                 if (((Relation)osm).isMultipolygon()) {
                     addIfNotNull(sl, AreaElemStyle.create(c));
-                    addIfNotNull(sl, LineElemStyle.createLine(c));
-                    addIfNotNull(sl, LineElemStyle.createCasing(c));
+                    addIfNotNull(sl, LineElemStyle.createLine(env));
+                    addIfNotNull(sl, LineElemStyle.createCasing(env));
                 } else if ("restriction".equals(osm.get("type"))) {
                     addIfNotNull(sl, NodeElemStyle.create(c));
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/Environment.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/Environment.java	(revision 3860)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/Environment.java	(revision 3860)
@@ -0,0 +1,26 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.mappaint;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.mappaint.Cascade;
+import org.openstreetmap.josm.gui.mappaint.MultiCascade;
+import org.openstreetmap.josm.gui.mappaint.StyleSource;
+
+public class Environment {
+    
+    public OsmPrimitive osm;
+    public MultiCascade mc;
+    public String layer;
+    public StyleSource source;
+
+    public Environment(OsmPrimitive osm, MultiCascade mc, String layer, StyleSource source) {
+        this.osm = osm;
+        this.mc = mc;
+        this.layer = layer;
+        this.source = source;
+    }
+
+    public Cascade getCascade() {
+        return mc.getCascade(layer);
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 3859)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 3860)
@@ -2,4 +2,7 @@
 package org.openstreetmap.josm.gui.mappaint;
 
+import static org.openstreetmap.josm.tools.Utils.equal;
+
+import java.awt.BasicStroke;
 import java.awt.Color;
 import java.util.Arrays;
@@ -11,4 +14,5 @@
 import org.openstreetmap.josm.data.osm.visitor.paint.MapPainter;
 import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
+import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction.RelativeFloat;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -16,31 +20,35 @@
 
     public static LineElemStyle createSimpleLineStyle(Color color) {
-        return new LineElemStyle(Cascade.EMPTY_CASCADE, -1f, 0f, color != null ? color : PaintColors.UNTAGGED.get(), null, 0f, null);
+        Cascade c = new Cascade();
+        c.put("width", -1f);
+        c.put("color", color != null ? color : PaintColors.UNTAGGED.get());
+        MultiCascade mc = new MultiCascade();
+        mc.put("default", c);
+        return createLine(new Environment(null, mc, "default", null));
     }
     public static final LineElemStyle UNTAGGED_WAY = createSimpleLineStyle(null);
 
-    private float width;
     public float realWidth; // the real width of this line in meter
     public Color color;
-    private float[] dashed;
-    private float dashesOffset;
-    public Color dashedColor;
-
-    protected LineElemStyle(Cascade c, float width, float realWidth, Color color, float[] dashed, float dashesOffset, Color dashedColor) {
+    public Color dashesBackground;
+
+    private BasicStroke line;
+    private BasicStroke dashesLine;
+
+    protected LineElemStyle(Cascade c, BasicStroke line, Color color, BasicStroke dashesLine, Color dashesBackground, float realWidth) {
         super(c);
-        setWidth(width);
+        this.line = line;
+        this.color = color;
+        this.dashesLine = dashesLine;
+        this.dashesBackground = dashesBackground;
         this.realWidth = realWidth;
-        this.color = color;
-        this.dashed = dashed;
-        this.dashesOffset = dashesOffset;
-        this.dashedColor = dashedColor;
-    }
-
-    public static LineElemStyle createLine(Cascade c) {
-        return createImpl(c, "");
-    }
-
-    public static LineElemStyle createCasing(Cascade c) {
-        LineElemStyle casing =  createImpl(c, "casing-");
+    }
+
+    public static LineElemStyle createLine(Environment env) {
+        return createImpl(env, "");
+    }
+
+    public static LineElemStyle createCasing(Environment env) {
+        LineElemStyle casing =  createImpl(env, "casing-");
         if (casing != null) {
             casing.object_z_index = -1;
@@ -49,10 +57,44 @@
     }
 
-    private static LineElemStyle createImpl(Cascade c, String prefix) {
-        Float width = c.get(prefix + "width", null, Float.class);
-        if (width == null)
-            return null;
+    private static LineElemStyle createImpl(Environment env, String prefix) {
+        Cascade c = env.getCascade();
+        Float width = c.get(prefix + "width", null, Float.class, true);
+        if (width != null) {
+            if (width == -1f) {
+                width = (float) MapPaintSettings.INSTANCE.getDefaultSegmentWidth();
+            }
+            if (width <= 0)
+                return null;
+        } else {
+            String width_key = c.get(prefix + "width", null, String.class, true);
+            if (equal(width_key, "thinnest")) {
+                width = 0f;
+            } else if (! equal(env.layer, "default")) {
+                RelativeFloat width_rel = c.get(prefix + "width", null, RelativeFloat.class, true);
+                if (width_rel != null) {
+                    width = env.mc.getCascade("default").get("width", 0f, Float.class) + width_rel.val;
+                } else
+                    return null;
+            } else
+                return null;
+        }
 
         float realWidth = c.get(prefix + "real-width", 0f, Float.class);
+        if (realWidth > 0 && MapPaintSettings.INSTANCE.isUseRealWidth()) {
+
+            /* if we have a "width" tag, try use it */
+            String widthTag = env.osm.get("width");
+            if(widthTag == null) {
+                widthTag = env.osm.get("est_width");
+            }
+            if(widthTag != null) {
+                try {
+                    realWidth = new Float(Integer.parseInt(widthTag));
+                }
+                catch(NumberFormatException nfe) {
+                }
+            }
+        }
+
         Color color = c.get(prefix + "color", null, Color.class);
         if (color == null) {
@@ -82,5 +124,5 @@
                 }
             }
-            if (!hasPositive) {
+            if (!hasPositive || dashes.length == 0) {
                 dashes = null;
             }
@@ -97,5 +139,41 @@
         }
 
-        return new LineElemStyle(c, width, realWidth, color, dashes, dashesOffset, dashesBackground);
+        int cap;
+        String capStr = c.get(prefix + "linecap", null, String.class);
+        if (equal(capStr, "none")) {
+            cap = BasicStroke.CAP_BUTT;
+        } else if (equal(capStr, "round")) {
+            cap = BasicStroke.CAP_ROUND;
+        } else if (equal(capStr, "square")) {
+            cap = BasicStroke.CAP_SQUARE;
+        } else {
+            cap = dashes != null ? BasicStroke.CAP_BUTT : BasicStroke.CAP_ROUND;
+        }
+
+        int join;
+        String joinStr = c.get(prefix + "linejoin", null, String.class);
+        if (equal(joinStr, "round")) {
+            join = BasicStroke.JOIN_ROUND;
+        } else if (equal(joinStr, "miter")) {
+            join = BasicStroke.JOIN_MITER;
+        } else if (equal(joinStr, "bevel")) {
+            join = BasicStroke.JOIN_BEVEL;
+        } else {
+            join = BasicStroke.JOIN_ROUND;
+        }
+
+        float miterlimit = c.get(prefix + "miterlimit", 10f, Float.class);
+
+        BasicStroke line = new BasicStroke(width, cap, join, miterlimit, dashes, dashesOffset);
+        BasicStroke dashesLine = null;
+
+        if (dashes != null && dashesBackground != null) {
+            float[] dashes2 = new float[dashes.length];
+            System.arraycopy(dashes, 0, dashes2, 1, dashes.length - 1);
+            dashes2[0] = dashes[dashes.length-1];
+            dashesLine = new BasicStroke(width, cap, join, miterlimit, dashes2, dashes2[0] + dashesOffset);
+        }
+
+        return new LineElemStyle(c, line, color, dashesLine, dashesBackground, realWidth);
     }
 
@@ -114,26 +192,16 @@
         Node lastN;
 
-        Color myDashedColor = dashedColor;
-        float myWidth = getWidth();
-
+        Color myDashedColor = dashesBackground;
+        BasicStroke myLine = line, myDashLine = dashesLine;
         if (realWidth > 0 && paintSettings.isUseRealWidth() && !showDirection) {
-
-            /* if we have a "width" tag, try use it */
-            /* (this might be slow and could be improved by caching the value in the Way, on the other hand only used if "real width" is enabled) */
-            String widthTag = w.get("width");
-            if(widthTag == null) {
-                widthTag = w.get("est_width");
-            }
-            if(widthTag != null) {
-                try {
-                    realWidth = new Float(Integer.parseInt(widthTag));
-                }
-                catch(NumberFormatException nfe) {
-                }
-            }
-
-            myWidth = (int) (100 /  (float) (painter.getCircum() / realWidth));
-            if (myWidth < getWidth()) {
-                myWidth = getWidth();
+            float myWidth = (int) (100 /  (float) (painter.getCircum() / realWidth));
+            if (myWidth < line.getLineWidth()) {
+                myWidth = line.getLineWidth();
+            }
+            myLine = new BasicStroke(myWidth, line.getEndCap(), line.getLineJoin(), 
+                    line.getMiterLimit(), line.getDashArray(), line.getDashPhase());
+            if (dashesLine != null) {
+                myDashLine = new BasicStroke(myWidth, dashesLine.getEndCap(), dashesLine.getLineJoin(),
+                        dashesLine.getMiterLimit(), dashesLine.getDashArray(), dashesLine.getDashPhase());
             }
         }
@@ -151,6 +219,5 @@
         }
 
-        painter.drawWay(w, markColor != null ? markColor : color, myWidth, dashed, 
-                dashesOffset, myDashedColor, showDirection,
+        painter.drawWay(w, markColor != null ? markColor : color, myLine, myDashLine, myDashedColor, showDirection,
                 selected ? false : reversedDirection, showOnlyHeadArrowOnly);
 
@@ -168,14 +235,4 @@
     }
 
-    public float getWidth() {
-        if (width == -1f)
-            return MapPaintSettings.INSTANCE.getDefaultSegmentWidth();
-        return width;
-    }
-
-    public void setWidth(float width) {
-        this.width = width;
-    }
-
     @Override
     public boolean equals(Object obj) {
@@ -185,10 +242,9 @@
             return false;
         final LineElemStyle other = (LineElemStyle) obj;
-        return width == other.width &&
-                realWidth == other.realWidth &&
-                Utils.equal(color, other.color) &&
-                Arrays.equals(dashed, other.dashed) &&
-                dashesOffset == other.dashesOffset &&
-                Utils.equal(dashedColor, other.dashedColor);
+        return  equal(line, other.line) &&
+                equal(color, other.color) &&
+                equal(dashesLine, other.dashesLine) &&
+                equal(dashesBackground, other.dashesBackground) &&
+                realWidth == other.realWidth;
     }
 
@@ -196,10 +252,9 @@
     public int hashCode() {
         int hash = super.hashCode();
-        hash = 29 * hash + Float.floatToIntBits(width);
+        hash = 29 * hash + line.hashCode();
+        hash = 29 * hash + color.hashCode();
+        hash = 29 * hash + (dashesLine != null ? dashesLine.hashCode() : 0);
+        hash = 29 * hash + (dashesBackground != null ? dashesBackground.hashCode() : 0);
         hash = 29 * hash + Float.floatToIntBits(realWidth);
-        hash = 29 * hash + color.hashCode();
-        hash = 29 * hash + Arrays.hashCode(dashed);
-        hash = 29 * hash + Float.floatToIntBits(dashesOffset);
-        hash = 29 * hash + (dashedColor != null ? dashedColor.hashCode() : 0);
         return hash;
     }
@@ -207,9 +262,9 @@
     @Override
     public String toString() {
-        return "LineElemStyle{" + super.toString() + "width=" + width + 
+        return "LineElemStyle{" + super.toString() + "width=" + line.getLineWidth() +
                 " realWidth=" + realWidth + " color=" + Utils.toString(color) +
-                " dashed=" + Arrays.toString(dashed) +
-                (dashesOffset == 0f ? "" : " dashesOffses=" + dashesOffset) +
-                " dashedColor=" + Utils.toString(dashedColor) + '}';
+                " dashed=" + Arrays.toString(line.getDashArray()) +
+                (line.getDashPhase() == 0f ? "" : " dashesOffses=" + line.getDashPhase()) +
+                " dashedColor=" + Utils.toString(dashesBackground) + '}';
     }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java	(revision 3859)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java	(revision 3860)
@@ -4,4 +4,5 @@
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.gui.mappaint.Environment;
 import org.openstreetmap.josm.tools.Utils;
 
Index: unk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Environment.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Environment.java	(revision 3859)
+++ 	(revision )
@@ -1,26 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.mappaint.mapcss;
-
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.gui.mappaint.Cascade;
-import org.openstreetmap.josm.gui.mappaint.MultiCascade;
-import org.openstreetmap.josm.gui.mappaint.StyleSource;
-
-public class Environment {
-    
-    OsmPrimitive osm;
-    MultiCascade mc;
-    String layer;
-    StyleSource source;
-
-    public Environment(OsmPrimitive osm, MultiCascade mc, String layer, StyleSource source) {
-        this.osm = osm;
-        this.mc = mc;
-        this.layer = layer;
-        this.source = source;
-    }
-
-    public Cascade getCascade() {
-        return mc.getCascade(layer);
-    }
-}
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java	(revision 3859)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java	(revision 3860)
@@ -15,4 +15,5 @@
 import org.openstreetmap.josm.actions.search.SearchCompiler.ParseError;
 import org.openstreetmap.josm.gui.mappaint.Cascade;
+import org.openstreetmap.josm.gui.mappaint.Environment;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -137,4 +138,12 @@
                 }
                 return c.containsKey(key);
+            }
+
+            public String get_tag_value(String key) {
+                return env.osm.get(key);
+            }
+
+            public boolean has_tag_key(String key) {
+                return env.osm.hasKey(key);
             }
 
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java	(revision 3859)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java	(revision 3860)
@@ -4,4 +4,5 @@
 import java.util.Arrays;
 
+import org.openstreetmap.josm.gui.mappaint.Environment;
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
 
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java	(revision 3859)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java	(revision 3860)
@@ -13,4 +13,5 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.gui.mappaint.Cascade;
+import org.openstreetmap.josm.gui.mappaint.Environment;
 import org.openstreetmap.josm.gui.mappaint.MultiCascade;
 import org.openstreetmap.josm.gui.mappaint.Range;
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java	(revision 3859)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java	(revision 3860)
@@ -8,4 +8,5 @@
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.gui.mappaint.Environment;
 import org.openstreetmap.josm.gui.mappaint.Range;
 import org.openstreetmap.josm.tools.Pair;
