Index: /trunk/src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java	(revision 11143)
+++ /trunk/src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java	(revision 11144)
@@ -233,9 +233,10 @@
             // Non-native highlighting is used, because sometimes highlighted
             // segments are covered with others, which is bad.
-            g.setStroke(SELECT_TARGET_WAY_STROKE.get());
+            BasicStroke stroke = SELECT_TARGET_WAY_STROKE.get();
+            g.setStroke(stroke);
 
             List<Node> nodes = targetWay.getNodes();
 
-            g.draw(new MapViewPath(mv).append(nodes, false));
+            g.draw(new MapViewPath(mv).append(nodes, false).computeClippedLine(stroke));
 
         } else if (state == State.IMPROVING) {
@@ -301,5 +302,5 @@
                 }
             }
-            g.draw(b);
+            g.draw(b.computeClippedLine(g.getStroke()));
 
             // Highlighting candidateNode
@@ -313,5 +314,5 @@
                 drawIntersectingWayHelperLines(mv, b);
                 g.setStroke(MOVE_NODE_INTERSECTING_STROKE.get());
-                g.draw(b);
+                g.draw(b.computeClippedLine(g.getStroke()));
             }
 
Index: /trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java	(revision 11143)
+++ /trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java	(revision 11144)
@@ -471,5 +471,5 @@
             line.moveTo(referenceSegment.getFirstNode());
             line.lineTo(referenceSegment.getSecondNode());
-            g.draw(line);
+            g.draw(line.computeClippedLine(g.getStroke()));
 
             g.setStroke(HELPER_LINE_STROKE.get());
@@ -478,5 +478,5 @@
             line.moveTo(helperLineStart);
             line.lineTo(helperLineEnd);
-            g.draw(line);
+            g.draw(line.computeClippedLine(g.getStroke()));
         }
     }
Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 11143)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 11144)
@@ -451,5 +451,5 @@
     }
 
-    private void displaySegments(Path2D path, Path2D orientationArrows, Path2D onewayArrows, Path2D onewayArrowsCasing,
+    private void displaySegments(MapViewPath path, Path2D orientationArrows, Path2D onewayArrows, Path2D onewayArrowsCasing,
             Color color, BasicStroke line, BasicStroke dashes, Color dashedColor) {
         g.setColor(isInactiveMode ? inactiveColor : color);
@@ -457,10 +457,10 @@
             g.setStroke(line);
         }
-        g.draw(path);
+        g.draw(path.computeClippedLine(g.getStroke()));
 
         if (!isInactiveMode && useStrokes && dashes != null) {
             g.setColor(dashedColor);
             g.setStroke(dashes);
-            g.draw(path);
+            g.draw(path.computeClippedLine(dashes));
         }
 
@@ -1030,5 +1030,5 @@
      * @param line line style
      */
-    private void drawPathHighlight(Path2D path, BasicStroke line) {
+    private void drawPathHighlight(MapViewPath path, BasicStroke line) {
         if (path == null)
             return;
Index: /trunk/src/org/openstreetmap/josm/gui/MapViewState.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/MapViewState.java	(revision 11143)
+++ /trunk/src/org/openstreetmap/josm/gui/MapViewState.java	(revision 11144)
@@ -553,5 +553,5 @@
          * @since 10874
          */
-        public MapViewPoint interpolate(MapViewPoint p1, int i) {
+        public MapViewPoint interpolate(MapViewPoint p1, double i) {
             return new MapViewViewPoint((1 - i) * getInViewX() + i * p1.getInViewX(), (1 - i) * getInViewY() + i * p1.getInViewY());
         }
Index: /trunk/src/org/openstreetmap/josm/gui/draw/MapViewPath.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/draw/MapViewPath.java	(revision 11143)
+++ /trunk/src/org/openstreetmap/josm/gui/draw/MapViewPath.java	(revision 11144)
@@ -2,6 +2,8 @@
 package org.openstreetmap.josm.gui.draw;
 
-import java.awt.geom.Point2D;
-import java.text.MessageFormat;
+import java.awt.BasicStroke;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.geom.PathIterator;
 
 import org.openstreetmap.josm.data.coor.EastNorth;
@@ -12,8 +14,10 @@
 import org.openstreetmap.josm.gui.MapViewState.MapViewRectangle;
 
+
 /**
  * This is a version of a java Path2D that allows you to add points to it by simply giving their east/north, lat/lon or node coordinates.
  * <p>
- * Paths far outside the view area are automatically clipped to increase performance.
+ * It is possible to clip the part of the path that is outside the view. This is useful when drawing dashed lines. Those lines use up a lot of
+ * performance if the zoom level is high and the part outside the view is long. See {@link #computeClippedLine(Stroke)}.
  * @author Michael Zangl
  * @since 10875
@@ -91,31 +95,5 @@
     @Override
     public MapViewPath lineTo(MapViewPoint p) {
-        Point2D currentPoint = getCurrentPoint();
-        if (currentPoint == null) {
-            throw new IllegalStateException("Path not started yet.");
-        }
-        MapViewPoint current = state.getForView(currentPoint.getX(), currentPoint.getY());
-        MapViewPoint end = p;
-
-        MapViewRectangle clip = state.getViewClipRectangle();
-        MapViewPoint entry = clip.getLineEntry(current, end);
-        if (entry == null) {
-            // skip this one - outside the view.
-            super.moveTo(end);
-        } else {
-            if (!entry.equals(current)) {
-                super.moveTo(entry);
-            }
-            MapViewPoint exit = clip.getLineEntry(end, current);
-            if (exit == null) {
-                throw new AssertionError(MessageFormat.format(
-                        "getLineEntry produces wrong results when doing the reverse lookup. Attempt: {0}->{1}",
-                        end.getEastNorth(), current.getEastNorth()));
-            }
-            super.lineTo(exit);
-            if (!exit.equals(end)) {
-                super.moveTo(end);
-            }
-        }
+        super.lineTo(p);
         return this;
     }
@@ -191,3 +169,125 @@
         }
     }
+
+    /**
+     * Compute a line that is similar to the current path expect for that parts outside the screen are skipped using moveTo commands.
+     *
+     * The line is computed in a way that dashes stay in their place when moving the view.
+     *
+     * The resulting line is not intended to fill areas.
+     * @param stroke The stroke to compute the line for.
+     * @return The new line shape.
+     */
+    public Shape computeClippedLine(Stroke stroke) {
+        if (stroke instanceof BasicStroke && ((BasicStroke) stroke).getDashArray() != null) {
+            float length = 0;
+            for (float f : ((BasicStroke) stroke).getDashArray()) {
+                length += f;
+            }
+            return computeClippedLine(((BasicStroke) stroke).getDashPhase(), length);
+        } 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 {
+        private final MapViewRectangle clip;
+        private double strokeOffset;
+        private final double strokeLength;
+        private MapViewPoint lastMoveTo;
+
+        private MapViewPoint cursor;
+        private boolean cursorIsActive = false;
+
+        ClampingPathVisitor(MapViewRectangle clip, double strokeOffset, double strokeLength) {
+            this.clip = clip;
+            this.strokeOffset = strokeOffset;
+            this.strokeLength = strokeLength;
+        }
+
+        /**
+         * Append a path to this one. The path is clipped to the current view.
+         * @param it The iterator
+         * @return true if adding the path was successful.
+         */
+        public boolean visit(PathIterator it) {
+            double[] coords = new double[8];
+            while (!it.isDone()) {
+                int type = it.currentSegment(coords);
+                switch (type) {
+                case PathIterator.SEG_CLOSE:
+                    visitClose();
+                    break;
+                case PathIterator.SEG_LINETO:
+                    visitLineTo(coords[0], coords[1]);
+                    break;
+                case PathIterator.SEG_MOVETO:
+                    visitMoveTo(coords[0], coords[1]);
+                    break;
+                default:
+                    // cannot handle this shape - this should be very rare. We let Java2D do the clipping.
+                    return false;
+                }
+                it.next();
+            }
+            return true;
+        }
+
+        void visitClose() {
+            drawLineTo(lastMoveTo);
+        }
+
+        void visitMoveTo(double x, double y) {
+            MapViewPoint point = state.getForView(x, y);
+            lastMoveTo = point;
+            cursor = point;
+        }
+
+        void visitLineTo(double x, double y) {
+            drawLineTo(state.getForView(x, y));
+        }
+
+        private void drawLineTo(MapViewPoint next) {
+            MapViewPoint entry = clip.getLineEntry(cursor, next);
+            if (entry != null) {
+                MapViewPoint exit = clip.getLineEntry(next, cursor);
+                if (!cursorIsActive || !entry.equals(cursor)) {
+                    entry = alignStrokeOffset(entry, cursor);
+                    moveTo(entry);
+                }
+                lineTo(exit);
+                cursorIsActive = exit.equals(next);
+            }
+            strokeOffset += cursor.distanceToInView(next);
+
+            cursor = next;
+        }
+
+        private MapViewPoint alignStrokeOffset(MapViewPoint entry, MapViewPoint originalStart) {
+            double distanceSq = entry.distanceToInViewSq(originalStart);
+            if (distanceSq < 0.01 || strokeLength <= 0.001) {
+                // don't move if there is nothing to move.
+                return entry;
+            }
+
+            double distance = Math.sqrt(distanceSq);
+            double offset = ((strokeOffset + distance)) % strokeLength;
+            if (offset < 0.01) {
+                return entry;
+            }
+
+            return entry.interpolate(originalStart, offset / distance);
+        }
+
+    }
 }
