Index: trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(revision 8259)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(revision 8260)
@@ -120,12 +120,19 @@
             symbol = createSymbol(env);
         }
-        final String rotationString = c.get("icon-rotation", null, String.class);
         RotationAngle rotationAngle = null;
-        if ("way".equalsIgnoreCase(rotationString)) {
-            rotationAngle = RotationAngle.buildWayDirectionRotation();
-        } else if (rotationString != null) {
-            try {
-                rotationAngle = RotationAngle.buildStaticRotation(rotationString);
-            } catch (RuntimeException ignore) {
+        final Float angle = c.get(ICON_ROTATION, null, Float.class, true);
+        if (angle != null) {
+            rotationAngle = RotationAngle.buildStaticRotation(angle);
+        } else {
+            final Keyword rotationKW = c.get(ICON_ROTATION, null, Keyword.class);
+            if (rotationKW != null) {
+                if ("way".equals(rotationKW.val)) {
+                    rotationAngle = RotationAngle.buildWayDirectionRotation();
+                } else {
+                    try {
+                        rotationAngle = RotationAngle.buildStaticRotation(rotationKW.val);
+                    } catch (IllegalArgumentException ignore) {
+                    }
+                }
             }
         }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/StyleKeys.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/StyleKeys.java	(revision 8259)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/StyleKeys.java	(revision 8260)
@@ -21,4 +21,5 @@
     String ICON_OFFSET_Y = "icon-offset-y";
     String ICON_OPACITY = "icon-opacity";
+    String ICON_ROTATION = "icon-rotation";
     String ICON_WIDTH = "icon-width";
     String LINECAP = "linecap";
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj	(revision 8259)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj	(revision 8260)
@@ -20,4 +20,5 @@
 import org.openstreetmap.josm.gui.mappaint.mapcss.Expression;
 import org.openstreetmap.josm.gui.mappaint.mapcss.ExpressionFactory;
+import org.openstreetmap.josm.gui.mappaint.mapcss.ExpressionFactory.NullExpression;
 import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction;
 import org.openstreetmap.josm.gui.mappaint.mapcss.LiteralExpression;
@@ -184,4 +185,5 @@
 |   < CARET: "^" >
 |   < FULLSTOP: "." >
+|   < DEG: "°" >
 |   < ELEMENT_OF: "∈" >
 |   < CROSSING: "⧉" >
@@ -1028,5 +1030,10 @@
         fn=function() { return fn; }
     |
-        lit=literal() { return new LiteralExpression(lit); }
+        lit=literal()
+        { 
+            if (lit == null)
+                return NullExpression.INSTANCE;
+            return new LiteralExpression(lit);
+        }
     |
         <LPAR> w() nested=expression() <RPAR> { return nested; }
@@ -1054,5 +1061,5 @@
     String val, pref;
     Token t;
-    float f;
+    Float f;
 }
 {
@@ -1067,7 +1074,49 @@
         <PLUS> f=ufloat() { return new Instruction.RelativeFloat(f); }
     |
+        LOOKAHEAD(2)
+        f=ufloat_unit() { return f; }
+    |
         f=ufloat() { return f; }
     |
         t=<HEXCOLOR> { return ColorHelper.html2color(t.image); }
+}
+
+/**
+ * Number followed by a unit.
+ *
+ * Returns angles in radians and lengths in pixels.
+ */
+Float ufloat_unit() :
+{
+    float f;
+    String u;
+}
+{
+    f=ufloat() ( u=ident() | <DEG> { u = "°"; } )
+    {
+        Double m = unit_factor(u);
+        if (m == null)
+            return null;
+        return (float) (f * m);
+    }
+}
+
+JAVACODE
+private Double unit_factor(String unit) {
+    switch (unit) {
+        case "deg":
+        case "°": return Math.PI / 180;
+        case "rad": return 1.;
+        case "grad": return Math.PI / 200;
+        case "turn": return 2 * Math.PI;
+        case "px": return 1.;
+        case "cm": return 96/2.54;
+        case "mm": return 9.6/2.54;
+        case "in": return 96.;
+        case "q": return 2.4/2.54;
+        case "pc": return 16.;
+        case "pt": return 96./72;
+        default: return null;
+    }
 }
 
Index: trunk/src/org/openstreetmap/josm/gui/util/RotationAngle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/util/RotationAngle.java	(revision 8259)
+++ trunk/src/org/openstreetmap/josm/gui/util/RotationAngle.java	(revision 8260)
@@ -41,24 +41,9 @@
      */
     public static RotationAngle buildStaticRotation(final String string) {
-        final Pattern radiansPattern = Pattern.compile("(\\d+\\.?\\d*)\\s*(rad)?");
-        final Pattern degreesPattern = Pattern.compile("(\\d+\\.?\\d*)\\s*(deg|°)");
-        final Pattern gradianPattern = Pattern.compile("(\\d+\\.?\\d*)\\s*(grad)");
-        final Pattern turnPattern = Pattern.compile("(\\d+\\.?\\d*)\\s*(turn)");
         final double value;
-        Matcher matcher;
-        if ((matcher = radiansPattern.matcher(string)).matches()) {
-            value = Double.parseDouble(matcher.group(1));
-        } else if ((matcher = degreesPattern.matcher(string)).matches()) {
-            value = Math.toRadians(Double.parseDouble(matcher.group(1)));
-        } else if ((matcher = gradianPattern.matcher(string)).matches()) {
-            value = Double.parseDouble(matcher.group(1)) / 200 * Math.PI;
-        } else if ((matcher = turnPattern.matcher(string)).matches()) {
-            value = Double.parseDouble(matcher.group(1)) * 2 * Math.PI;
-        } else {
-            try {
-                value = parseCardinalRotation(string);
-            } catch (IllegalArgumentException ignore) {
-                throw new IllegalArgumentException("Invalid string: " + string);
-            }
+        try {
+            value = parseCardinalRotation(string);
+        } catch (IllegalArgumentException ignore) {
+            throw new IllegalArgumentException("Invalid string: " + string);
         }
         return buildStaticRotation(value);
