Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 4316)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 4317)
@@ -24,4 +24,5 @@
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.List;
 
 import javax.swing.ImageIcon;
@@ -114,5 +115,5 @@
      * @param onewayReversed for oneway=-1 and similar
      */
-    public void drawWay(Way way, Color color, BasicStroke line, BasicStroke dashes, Color dashedColor,
+    public void drawWay(Way way, Color color, BasicStroke line, BasicStroke dashes, Color dashedColor, int offset,
             boolean showOrientation, boolean showHeadArrowOnly,
             boolean showOneway, boolean onewayReversed) {
@@ -128,9 +129,11 @@
         Point lastPoint = null;
         boolean initialMoveToNeeded = true;
-        Iterator<Node> it = way.getNodes().iterator();
+        List<Node> wayNodes = way.getNodes();
+        if (wayNodes.size() < 2) return;
+        
+        Iterator<Point> it = new OffsetIterator(way.getNodes(), offset);
         while (it.hasNext()) {
-            Node n = it.next();
-            Point p = nc.getPoint(n);
-            if(lastPoint != null) {
+            Point p = it.next();
+            if (lastPoint != null) {
                 Point p1 = lastPoint;
                 Point p2 = p;
@@ -209,4 +212,100 @@
     }
 
+    /**
+     * Iterates over a list of Way Nodes and returns screen coordinates that
+     * represent a line that is shifted by a certain offset perpendicular
+     * to the way direction.
+     * 
+     * There is no intention, to handle consecutive duplicate Nodes in a
+     * perfect way, but it is should not throw an exception.
+     */
+    public class OffsetIterator implements Iterator<Point> {
+        
+        private List<Node> nodes;
+        private int offset;
+        private int idx;
+        
+        private Point prev = null;
+        /* 'prev0' is a point that has distance 'offset' from 'prev' and the
+         * line from 'prev' to 'prev0' is perpendicular to the way segment from
+         * 'prev' to the next point.
+         */
+        private int x_prev0, y_prev0;
+
+        public OffsetIterator(List<Node> nodes, int offset) {
+            this.nodes = nodes;
+            this.offset = offset;
+            idx = 0;
+        }
+        
+        @Override
+        public boolean hasNext() {
+            return idx < nodes.size();
+        }
+
+        @Override
+        public Point next() {
+            if (offset == 0) return nc.getPoint(nodes.get(idx++));
+            
+            Point current = nc.getPoint(nodes.get(idx));
+            
+            if (idx == nodes.size() - 1) {
+                ++idx;
+                return new Point(x_prev0 + current.x - prev.x, y_prev0 + current.y - prev.y);
+            }
+
+            Point next = nc.getPoint(nodes.get(idx+1));
+
+            int dx_next = next.x - current.x;
+            int dy_next = next.y - current.y;
+            double len_next = Math.sqrt(dx_next*dx_next + dy_next*dy_next);
+
+            if (len_next == 0) {
+                len_next = 1; // value does not matter, because dy_next and dx_next is 0
+            }
+
+            int x_current0 = current.x + (int) Math.round(offset * dy_next / len_next);
+            int y_current0 = current.y - (int) Math.round(offset * dx_next / len_next);
+
+            if (idx==0) {
+                ++idx;
+                prev = current;
+                x_prev0 = x_current0;
+                y_prev0 = y_current0;
+                return new Point(x_current0, y_current0);
+            } else {
+                int dx_prev = current.x - prev.x;
+                int dy_prev = current.y - prev.y;
+                
+                // determine intersection of the lines parallel to the two
+                // segments
+                int det = dx_next*dy_prev - dx_prev*dy_next;
+                
+                if (det == 0) {
+                    ++idx;
+                    prev = current;
+                    x_prev0 = x_current0;
+                    y_prev0 = y_current0;
+                    return new Point(x_current0, y_current0);
+                }
+
+                int m = dx_next*(y_current0 - y_prev0) - dy_next*(x_current0 - x_prev0);
+
+                int cx_ = x_prev0 + (int) Math.round(m * dx_prev / det);
+                int cy_ = y_prev0 + (int) Math.round(m * dy_prev / det);
+                ++idx;
+                prev = current;
+                x_prev0 = x_current0;
+                y_prev0 = y_current0;
+                return new Point(cx_, cy_);
+            }
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+    
     private void displaySegments(GeneralPath path, GeneralPath orientationArrows, GeneralPath onewayArrows, GeneralPath onewayArrowsCasing,
             Color color, BasicStroke line, BasicStroke dashes, Color dashedColor) {
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 4316)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 4317)
@@ -202,5 +202,5 @@
     @Override
     public void render(final DataSet data, boolean renderVirtualNodes, Bounds bounds) {
-        long start = System.currentTimeMillis();
+        //long start = System.currentTimeMillis();
         BBox bbox = new BBox(bounds);
 
@@ -226,11 +226,11 @@
         collectWayStyles(data, sc, bbox);
         collectRelationStyles(data, sc, bbox);
-        long phase1 = System.currentTimeMillis();
+        //long phase1 = System.currentTimeMillis();
         sc.drawAll();
         sc = null;
         painter.drawVirtualNodes(data.searchWays(bbox));
 
-        long now = System.currentTimeMillis();
-        System.err.println(String.format("PAINTING TOOK %d [PHASE1 took %d] (at scale %s)", now - start, phase1 - start, circum));
+        //long now = System.currentTimeMillis();
+        //System.err.println(String.format("PAINTING TOOK %d [PHASE1 took %d] (at scale %s)", now - start, phase1 - start, circum));
     }
 }
