Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 5205)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 5206)
@@ -127,5 +127,5 @@
      * @param onewayReversed for oneway=-1 and similar
      */
-    public void drawWay(Way way, Color color, BasicStroke line, BasicStroke dashes, Color dashedColor, int offset,
+    public void drawWay(Way way, Color color, BasicStroke line, BasicStroke dashes, Color dashedColor, float offset,
             boolean showOrientation, boolean showHeadArrowOnly,
             boolean showOneway, boolean onewayReversed) {
@@ -259,5 +259,5 @@
 
         private List<Node> nodes;
-        private int offset;
+        private float offset;
         private int idx;
 
@@ -269,5 +269,5 @@
         private int x_prev0, y_prev0;
 
-        public OffsetIterator(List<Node> nodes, int offset) {
+        public OffsetIterator(List<Node> nodes, float offset) {
             this.nodes = nodes;
             this.offset = offset;
@@ -282,5 +282,5 @@
         @Override
         public Point next() {
-            if (offset == 0) return nc.getPoint(nodes.get(idx++));
+            if (Math.abs(offset) < 0.1f) return nc.getPoint(nodes.get(idx++));
 
             Point current = nc.getPoint(nodes.get(idx));
@@ -861,5 +861,5 @@
             if ((pb.width >= nb.getWidth() && pb.height >= nb.getHeight()) && // quick check
                     area.contains(centeredNBounds) // slow but nice
-                    ) {
+            ) {
                 g.setColor(text.color);
                 Font defaultFont = g.getFont();
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 5205)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 5206)
@@ -311,4 +311,6 @@
                 addIfNotNull(sl, LinePatternElemStyle.create(env));
                 addIfNotNull(sl, LineElemStyle.createLine(env));
+                addIfNotNull(sl, LineElemStyle.createLeftCasing(env));
+                addIfNotNull(sl, LineElemStyle.createRightCasing(env));
                 addIfNotNull(sl, LineElemStyle.createCasing(env));
                 addIfNotNull(sl, LineTextElemStyle.create(env));
@@ -347,7 +349,6 @@
      */
     private boolean isDefaultNodes() {
-        if (defaultNodesIdx == cacheIdx) {
+        if (defaultNodesIdx == cacheIdx)
             return defaultNodes;
-        }
         defaultNodes = fromCanvas("default-points", true, Boolean.class);
         defaultNodesIdx = cacheIdx;
@@ -359,7 +360,6 @@
      */
     private boolean isDefaultLines() {
-        if (defaultLinesIdx == cacheIdx) {
+        if (defaultLinesIdx == cacheIdx)
             return defaultLines;
-        }
         defaultLines = fromCanvas("default-lines", true, Boolean.class);
         defaultLinesIdx = cacheIdx;
@@ -420,11 +420,9 @@
      */
     public static AreaElemStyle getAreaElemStyle(OsmPrimitive p, boolean pretendWayIsClosed) {
-        if (MapPaintStyles.getStyles() == null) {
+        if (MapPaintStyles.getStyles() == null)
             return null;
-        }
         for (ElemStyle s : MapPaintStyles.getStyles().generateStyles(p, 1.0, null, pretendWayIsClosed).a) {
-            if (s instanceof AreaElemStyle) {
+            if (s instanceof AreaElemStyle)
                 return (AreaElemStyle) s;
-            }
         }
         return null;
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 5205)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 5206)
@@ -33,10 +33,10 @@
     public Color color;
     public Color dashesBackground;
-    public int offset;
+    public float offset;
     public float realWidth; // the real width of this line in meter
 
     private BasicStroke dashesLine;
 
-    protected LineElemStyle(Cascade c, BasicStroke line, Color color, BasicStroke dashesLine, Color dashesBackground, int offset, float realWidth) {
+    protected LineElemStyle(Cascade c, BasicStroke line, Color color, BasicStroke dashesLine, Color dashesBackground, float offset, float realWidth) {
         super(c, 0f);
         this.line = line;
@@ -49,9 +49,27 @@
 
     public static LineElemStyle createLine(Environment env) {
-        return createImpl(env, false);
+        return createImpl(env, "");
+    }
+
+    public static LineElemStyle createLeftCasing(Environment env) {
+        LineElemStyle leftCasing = createImpl(env, "left-casing-");
+        if (leftCasing != null) {
+            leftCasing.z_index += -90;
+            leftCasing.isModifier = true;
+        }
+        return leftCasing;
+    }
+
+    public static LineElemStyle createRightCasing(Environment env) {
+        LineElemStyle rightCasing = createImpl(env, "right-casing-");
+        if (rightCasing != null) {
+            rightCasing.z_index += -90;
+            rightCasing.isModifier = true;
+        }
+        return rightCasing;
     }
 
     public static LineElemStyle createCasing(Environment env) {
-        LineElemStyle casing =  createImpl(env, true);
+        LineElemStyle casing = createImpl(env, "casing-");
         if (casing != null) {
             casing.z_index += -100;
@@ -61,20 +79,13 @@
     }
 
-    private static LineElemStyle createImpl(Environment env, boolean casing) {
+    private static LineElemStyle createImpl(Environment env, String prefix) {
         Cascade c = env.mc.getCascade(env.layer);
         Cascade c_def = env.mc.getCascade("default");
 
-        String prefix = casing ? "casing-" : "";
-
-        Float width;
-        if (casing) {
-            Float widthOnDefault = getWidth(c_def, "width", null);
-            Float widthLine = getWidth(c, "width", widthOnDefault);
-            width = getWidth(c, "casing-width", widthLine);
-        } else {
-            Float widthOnDefault = getWidth(c_def, "width", null);
-            width = getWidth(c, "width", widthOnDefault);
-        }
-
+        Float widthOnDefault = getWidth(c_def, "width", null);
+        Float width = getWidth(c, "width", widthOnDefault);
+        if (!prefix.isEmpty()) {
+            width = getWidth(c, prefix + "width", width);
+        }
         if (width == null)
             return null;
@@ -97,6 +108,35 @@
         }
 
+        Float offsetOnDefault = getWidth(c_def, "offset", null);
+        Float offset = getWidth(c, "offset", offsetOnDefault);
+        if (offset == null) {
+            offset = 0f;
+        }
+        if (!prefix.isEmpty()) {
+            Float base_width = getWidth(c, "width", widthOnDefault);
+            Float base_offset = offset;
+            if (base_width == null || base_width < 2f) {
+                base_width = 2f;
+            }
+            /* pre-calculate an offset */
+            if (prefix.startsWith("left") || prefix.startsWith("right")) {
+                offset = base_width/2 + width/2;
+            } else {
+                offset = 0f;
+            }
+            /* overwrites (e.g. "4") or adjusts (e.g. "+4") a prefixed -offset */
+            if (getWidth(c, prefix + "offset", offset) != null) {
+                offset = getWidth(c, prefix + "offset", offset);
+            }
+            /* flip sign for the right-casing-offset */
+            if (prefix.startsWith("right")) {
+                offset *= -1f;
+            }
+            /* use base_offset as the reference center */
+            offset += base_offset;
+        }
+
         Color color = c.get(prefix + "color", null, Color.class);
-        if (!casing && color == null) {
+        if (prefix.isEmpty() && color == null) {
             color = c.get("fill-color", null, Color.class);
         }
@@ -177,6 +217,4 @@
         BasicStroke dashesLine = null;
 
-        float offset = c.get("offset", 0f, Float.class);
-
         if (dashes != null && dashesBackground != null) {
             float[] dashes2 = new float[dashes.length];
@@ -186,5 +224,5 @@
         }
 
-        return new LineElemStyle(c, line, color, dashesLine, dashesBackground, (int) offset, realWidth);
+        return new LineElemStyle(c, line, color, dashesLine, dashesBackground, offset, realWidth);
     }
 
@@ -273,5 +311,5 @@
         hash = 29 * hash + (dashesLine != null ? dashesLine.hashCode() : 0);
         hash = 29 * hash + (dashesBackground != null ? dashesBackground.hashCode() : 0);
-        hash = 29 * hash + offset;
+        hash = 29 * hash + Float.floatToIntBits(offset);
         hash = 29 * hash + Float.floatToIntBits(realWidth);
         return hash;
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java	(revision 5205)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java	(revision 5206)
@@ -20,4 +20,5 @@
 import org.openstreetmap.josm.gui.mappaint.Environment;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
+import org.openstreetmap.josm.tools.ColorHelper;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -114,4 +115,12 @@
                 }
                 return c;
+            }
+
+            public Color html2color(String html) {
+                return ColorHelper.html2color(html);
+            }
+
+            public String color2html(Color c) {
+                return ColorHelper.color2html(c);
             }
 
