Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 11146)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 11147)
@@ -1449,6 +1449,6 @@
         MapViewPath path = new MapViewPath(mapState);
         MapViewPath orientationArrows = showOrientation ? new MapViewPath(mapState) : null;
-        MapViewPath onewayArrows = showOneway ? new MapViewPath(mapState) : null;
-        MapViewPath onewayArrowsCasing = showOneway ? new MapViewPath(mapState) : null;
+        MapViewPath onewayArrows;
+        MapViewPath onewayArrowsCasing;
         Rectangle bounds = g.getClipBounds();
         if (bounds != null) {
@@ -1457,5 +1457,4 @@
         }
 
-        boolean initialMoveToNeeded = true;
         List<Node> wayNodes = way.getNodes();
         if (wayNodes.size() < 2) return;
@@ -1482,4 +1481,5 @@
         double wayLength = 0;
         Iterator<MapViewPoint> it = new OffsetIterator(wayNodes, offset);
+        boolean initialMoveToNeeded = true;
         while (it.hasNext()) {
             MapViewPoint p = it.next();
@@ -1503,16 +1503,4 @@
                     final double segmentLength = p1.distanceToInView(p2);
                     if (segmentLength != 0) {
-                        final double nx = (p2.getInViewX() - p1.getInViewX()) / segmentLength;
-                        final double ny = (p2.getInViewY() - p1.getInViewY()) / segmentLength;
-
-                        final double interval = 60;
-                        // distance from p1
-                        double dist = interval - (wayLength % interval);
-
-                        while (dist < segmentLength) {
-                            appenOnewayPath(onewayReversed, p1, nx, ny, dist, 3d, onewayArrowsCasing);
-                            appenOnewayPath(onewayReversed, p1, nx, ny, dist, 2d, onewayArrows);
-                            dist += interval;
-                        }
                     }
                     wayLength += segmentLength;
@@ -1521,4 +1509,30 @@
             lastPoint = p;
         }
+        if (showOneway) {
+            onewayArrows = new MapViewPath(mapState);
+            onewayArrowsCasing = new MapViewPath(mapState);
+            double interval = 60;
+
+            path.visitClippedLine(0, 60, (inLineOffset, start, end, startIsOldEnd) -> {
+                double segmentLength = start.distanceToInView(end);
+                if (segmentLength > 0.001) {
+                    final double nx = (end.getInViewX() - start.getInViewX()) / segmentLength;
+                    final double ny = (end.getInViewY() - start.getInViewY()) / segmentLength;
+
+                    // distance from p1
+                    double dist = interval - (inLineOffset % interval);
+
+                    while (dist < segmentLength) {
+                        appenOnewayPath(onewayReversed, start, nx, ny, dist, 3d, onewayArrowsCasing);
+                        appenOnewayPath(onewayReversed, start, nx, ny, dist, 2d, onewayArrows);
+                        dist += interval;
+                    }
+                }
+            });
+        } else {
+            onewayArrows = null;
+            onewayArrowsCasing = null;
+        }
+
         if (way.isHighlighted()) {
             drawPathHighlight(path, line);
Index: /trunk/src/org/openstreetmap/josm/gui/draw/MapViewPath.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/draw/MapViewPath.java	(revision 11146)
+++ /trunk/src/org/openstreetmap/josm/gui/draw/MapViewPath.java	(revision 11147)
@@ -178,6 +178,30 @@
      * @param stroke The stroke to compute the line for.
      * @return The new line shape.
+     * @since 11147
      */
     public Shape computeClippedLine(Stroke stroke) {
+        MapPath2D clamped = new MapPath2D();
+        if (visitClippedLine(stroke, (inLineOffset, start, end, startIsOldEnd) -> {
+            if (!startIsOldEnd) {
+                clamped.moveTo(start);
+            }
+            clamped.lineTo(end);
+        })) {
+            return clamped;
+        } else {
+            // could not clip the path.
+            return this;
+        }
+    }
+
+    /**
+     * Visits all straight segments of this path. The segments are clamped to the view.
+     * If they are clamped, the start points are aligned with the pattern.
+     * @param stroke The stroke to take the dash information from.
+     * @param consumer The consumer to call for each segment
+     * @return false if visiting the path failed because there e.g. were non-straight segments.
+     * @since 11147
+     */
+    public boolean visitClippedLine(Stroke stroke, PathSegmentConsumer consumer) {
         if (stroke instanceof BasicStroke && ((BasicStroke) stroke).getDashArray() != null) {
             float length = 0;
@@ -185,23 +209,47 @@
                 length += f;
             }
-            return computeClippedLine(((BasicStroke) stroke).getDashPhase(), length);
+            return visitClippedLine(((BasicStroke) stroke).getDashPhase(), length, consumer);
         } else {
-            return computeClippedLine(0, 0);
-        }
-    }
-
-    private Shape computeClippedLine(double strokeOffset, double strokeLength) {
-        ClampingPathVisitor path = new ClampingPathVisitor(state.getViewClipRectangle(), strokeOffset, strokeLength);
-        if (path.visit(getPathIterator(null))) {
-            return path;
-        } else {
-            // could not clip the path.
-            return this;
-        }
-    }
-
-    private class ClampingPathVisitor extends MapPath2D {
+            return visitClippedLine(0, 0, consumer);
+        }
+    }
+
+    /**
+     * Visits all straight segments of this path. The segments are clamped to the view.
+     * If they are clamped, the start points are aligned with the pattern.
+     * @param strokeOffset The initial offset of the pattern
+     * @param strokeLength The dash pattern length. 0 to use no pattern.
+     * @param consumer The consumer to call for each segment
+     * @return false if visiting the path failed because there e.g. were non-straight segments.
+     * @since 11147
+     */
+    public boolean visitClippedLine(double strokeOffset, double strokeLength, PathSegmentConsumer consumer) {
+        return new ClampingPathVisitor(state.getViewClipRectangle(), strokeOffset, strokeLength, consumer)
+            .visit(this);
+    }
+
+
+    /**
+     * This class is used to visit the segments of this path.
+     * @author Michael Zangl
+     * @since 11147
+     */
+    public interface PathSegmentConsumer {
+
+        /**
+         * Add a line segment between two points
+         * @param inLineOffset The offset of start in the line
+         * @param start The start point
+         * @param end The end point
+         * @param startIsOldEnd If the start point equals the last end point.
+         */
+        void addLineBetween(double inLineOffset, MapViewPoint start, MapViewPoint end, boolean startIsOldEnd);
+
+    }
+
+    private class ClampingPathVisitor {
         private final MapViewRectangle clip;
-        private double strokeProgress;
+        private final PathSegmentConsumer consumer;
+        protected double strokeProgress;
         private final double strokeLength;
         private MapViewPoint lastMoveTo;
@@ -210,17 +258,26 @@
         private boolean cursorIsActive = false;
 
-        ClampingPathVisitor(MapViewRectangle clip, double strokeOffset, double strokeLength) {
+        /**
+         * Create a new {@link ClampingPathVisitor}
+         * @param clip View clip rectangle
+         * @param strokeOffset Initial stroke offset
+         * @param strokeLength Total length of a stroke sequence
+         * @param consumer The consumer to notify of the path segments.
+         */
+        ClampingPathVisitor(MapViewRectangle clip, double strokeOffset, double strokeLength, PathSegmentConsumer consumer) {
             this.clip = clip;
             this.strokeProgress = Math.min(strokeLength - strokeOffset, 0);
             this.strokeLength = strokeLength;
+            this.consumer = consumer;
         }
 
         /**
          * Append a path to this one. The path is clipped to the current view.
-         * @param it The iterator
+         * @param mapViewPath The iterator
          * @return true if adding the path was successful.
          */
-        public boolean visit(PathIterator it) {
+        public boolean visit(MapViewPath mapViewPath) {
             double[] coords = new double[8];
+            PathIterator it = mapViewPath.getPathIterator(null);
             while (!it.isDone()) {
                 int type = it.currentSegment(coords);
@@ -252,4 +309,5 @@
             lastMoveTo = point;
             cursor = point;
+            cursorIsActive = false;
         }
 
@@ -264,7 +322,6 @@
                 if (!cursorIsActive || !entry.equals(cursor)) {
                     entry = alignStrokeOffset(entry, cursor);
-                    moveTo(entry);
                 }
-                lineTo(exit);
+                consumer.addLineBetween(strokeProgress + cursor.distanceToInView(entry), entry, exit, cursorIsActive);
                 cursorIsActive = exit.equals(next);
             }
@@ -273,4 +330,5 @@
             cursor = next;
         }
+
 
         private MapViewPoint alignStrokeOffset(MapViewPoint entry, MapViewPoint originalStart) {
