Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 8198)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 8199)
@@ -734,5 +734,5 @@
     }
 
-    public void drawNodeIcon(Node n, MapImage img, boolean disabled, boolean selected, boolean member) {
+    public void drawNodeIcon(Node n, MapImage img, boolean disabled, boolean selected, boolean member, double theta) {
         Point p = nc.getPoint(n);
 
@@ -747,5 +747,7 @@
             g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
         }
+        g.rotate(theta, p.x, p.y);
         g.drawImage(img.getImage(disabled), p.x - w/2 + img.offsetX, p.y - h/2 + img.offsetY, nc);
+        g.rotate(-theta, p.x, p.y);
         g.setPaintMode();
         if (selected || member)
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(revision 8198)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(revision 8199)
@@ -19,4 +19,5 @@
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
 import org.openstreetmap.josm.gui.mappaint.StyleCache.StyleList;
+import org.openstreetmap.josm.gui.util.RotationAngle;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -26,4 +27,5 @@
 public class NodeElemStyle extends ElemStyle implements StyleKeys {
     public final MapImage mapImage;
+    public final RotationAngle mapImageAngle;
     public final Symbol symbol;
 
@@ -99,8 +101,9 @@
     public static final StyleList DEFAULT_NODE_STYLELIST_TEXT = new StyleList(NodeElemStyle.SIMPLE_NODE_ELEMSTYLE, BoxTextElemStyle.SIMPLE_NODE_TEXT_ELEMSTYLE);
 
-    protected NodeElemStyle(Cascade c, MapImage mapImage, Symbol symbol, float default_major_z_index) {
+    protected NodeElemStyle(Cascade c, MapImage mapImage, Symbol symbol, float default_major_z_index, RotationAngle rotationAngle) {
         super(c, default_major_z_index);
         this.mapImage = mapImage;
         this.symbol = symbol;
+        this.mapImageAngle = rotationAngle;
     }
 
@@ -117,4 +120,14 @@
             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) {
+            }
+        }
 
         // optimization: if we neither have a symbol, nor a mapImage
@@ -123,5 +136,5 @@
         if (!allowDefault && symbol == null && mapImage == null) return null;
 
-        return new NodeElemStyle(c, mapImage, symbol, default_major_z_index);
+        return new NodeElemStyle(c, mapImage, symbol, default_major_z_index, rotationAngle);
     }
 
@@ -257,5 +270,6 @@
             Node n = (Node) primitive;
             if (mapImage != null && painter.isShowIcons()) {
-                painter.drawNodeIcon(n, mapImage, painter.isInactiveMode() || n.isDisabled(), selected, member);
+                painter.drawNodeIcon(n, mapImage, painter.isInactiveMode() || n.isDisabled(), selected, member,
+                        mapImageAngle == null ? 0.0 : mapImageAngle.getRotationAngle(primitive));
             } else if (symbol != null) {
                 Color fillColor = symbol.fillColor;
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java	(revision 8198)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java	(revision 8199)
@@ -30,4 +30,5 @@
 import org.openstreetmap.josm.gui.mappaint.Cascade;
 import org.openstreetmap.josm.gui.mappaint.Environment;
+import org.openstreetmap.josm.gui.util.RotationAngle;
 import org.openstreetmap.josm.io.XmlWriter;
 import org.openstreetmap.josm.tools.ColorHelper;
@@ -547,4 +548,31 @@
 
         /**
+         * Converts an angle in degrees to radians.
+         * @param degree the angle in degrees
+         * @return the angle in radians
+         * @see Math#toRadians(double)
+         */
+        public static double degree_to_radians(double degree) {
+            return Math.toRadians(degree);
+        }
+
+        /**
+         * Converts an angle diven in cardinal directions to radians.
+         * The following values are supported: {@code n}, {@code north}, {@code ne}, {@code northeast},
+         * {@code e}, {@code east}, {@code se}, {@code southeast}, {@code s}, {@code south},
+         * {@code sw}, {@code southwest}, {@code w}, {@code west}, {@code nw}, {@code northwest}.
+         * @param cardinal the angle in cardinal directions.
+         * @see RotationAngle#parseCardinalRotation(String)
+         * @return the angle in radians
+         */
+        public static Double cardinal_to_radians(String cardinal) {
+            try {
+                return RotationAngle.parseCardinalRotation(cardinal);
+            } catch (IllegalArgumentException ignore) {
+                return null;
+            }
+        }
+
+        /**
          * Determines if the objects {@code a} and {@code b} are equal.
          * @param a First object
Index: trunk/src/org/openstreetmap/josm/gui/util/RotationAngle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/util/RotationAngle.java	(revision 8199)
+++ trunk/src/org/openstreetmap/josm/gui/util/RotationAngle.java	(revision 8199)
@@ -0,0 +1,120 @@
+package org.openstreetmap.josm.gui.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.tools.Geometry;
+import org.openstreetmap.josm.tools.SubclassFilteredCollection;
+import org.openstreetmap.josm.tools.Utils;
+
+/**
+ * Determines how an icon is to be rotated depending on the primitive to displayed.
+ */
+public abstract class RotationAngle {
+    /**
+     * Calculates the rotation angle depending on the primitive to displayed.
+     */
+    public abstract double getRotationAngle(OsmPrimitive p);
+
+    /**
+     * Always returns the fixed {@code angle}.
+     */
+    public static RotationAngle buildStaticRotation(final double angle) {
+        return new RotationAngle() {
+            @Override
+            public double getRotationAngle(OsmPrimitive p) {
+                return angle;
+            }
+        };
+    }
+
+    /**
+     * Parses the rotation angle from the specified {@code string}.
+     */
+    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 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 {
+            try {
+                value = parseCardinalRotation(string);
+            } catch (IllegalArgumentException ignore) {
+                throw new IllegalArgumentException("Invalid string: " + string);
+            }
+        }
+        return buildStaticRotation(value);
+    }
+
+    /**
+     * Converts an angle diven in cardinal directions to radians.
+     * The following values are supported: {@code n}, {@code north}, {@code ne}, {@code northeast},
+     * {@code e}, {@code east}, {@code se}, {@code southeast}, {@code s}, {@code south},
+     * {@code sw}, {@code southwest}, {@code w}, {@code west}, {@code nw}, {@code northwest}.
+     * @param cardinal the angle in cardinal directions
+     * @return the angle in radians
+     */
+    public static double parseCardinalRotation(final String cardinal) {
+        switch (cardinal.toLowerCase()) {
+            case "n":
+            case "north":
+                return Math.toRadians(0);
+            case "ne":
+            case "northeast":
+                return Math.toRadians(45);
+            case "e":
+            case "east":
+                return Math.toRadians(90);
+            case "se":
+            case "southeast":
+                return Math.toRadians(135);
+            case "s":
+            case "south":
+                return Math.toRadians(180);
+            case "sw":
+            case "southwest":
+                return Math.toRadians(225);
+            case "w":
+            case "west":
+                return Math.toRadians(270);
+            case "nw":
+            case "northwest":
+                return Math.toRadians(315);
+            default:
+                throw new IllegalArgumentException("Unexpected cardinal direction " + cardinal);
+        }
+    }
+
+    /**
+     * Computes the angle depending on the referencing way segment, or {@code 0} if none exists.
+     */
+    public static RotationAngle buildWayDirectionRotation() {
+        return new RotationAngle() {
+            @Override
+            public double getRotationAngle(OsmPrimitive p) {
+                if (!(p instanceof Node)) {
+                    return 0;
+                }
+                final Node n = (Node) p;
+                final SubclassFilteredCollection<OsmPrimitive, Way> ways = Utils.filteredCollection(n.getReferrers(), Way.class);
+                if (ways.isEmpty()) {
+                    return 0;
+                }
+                final Way w = ways.iterator().next();
+                final int idx = w.getNodes().indexOf(n);
+                if (idx == 0) {
+                    return -Geometry.getSegmentAngle(n.getEastNorth(), w.getNode(idx + 1).getEastNorth());
+                } else {
+                    return -Geometry.getSegmentAngle(w.getNode(idx - 1).getEastNorth(), n.getEastNorth());
+                }
+            }
+        };
+    }
+}
