Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/LineClip.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/LineClip.java	(revision 3562)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/LineClip.java	(revision 3565)
@@ -7,35 +7,48 @@
 import static java.awt.geom.Rectangle2D.OUT_BOTTOM;
 import java.awt.Point;
+import java.awt.Rectangle;
 
 /**
  * Computes the part of a line that is visible in a given rectangle.
  * Using int leads to overflow, so we need long int.
- * http://en.wikipedia.org/wiki/Cohen-Sutherland
  */
 public class LineClip {
     private Point p1, p2;
+    private final Rectangle clipBounds;
+
+    public LineClip(Point p1, Point p2, Rectangle clipBounds) {
+        this.p1 = p1;
+        this.p2 = p2;
+        this.clipBounds = clipBounds;
+    }
 
     /**
-     * The outcode of the point.
-     * We cannot use Rectangle.outcode since it does not work with long ints.
+     * run the clipping algorithm
+     * @return true if the some parts of the line lies within the clip bounds
      */
-    public int computeOutCode (long x, long y, long xmin, long ymin, long xmax, long ymax) {
-        int code = 0;
-        if (y > ymax) {
-            code |= OUT_TOP;
-        }
-        else if (y < ymin) {
-            code |= OUT_BOTTOM;
-        }
-        if (x > xmax) {
-            code |= OUT_RIGHT;
-        }
-        else if (x < xmin) {
-            code |= OUT_LEFT;
-        }
-        return code;
+    public boolean execute() {
+        return cohenSutherland(p1.x, p1.y, p2.x, p2.y, clipBounds.x , clipBounds.y, clipBounds.x + clipBounds.width, clipBounds.y + clipBounds.height);
     }
 
-    public boolean cohenSutherland( long x1, long y1, long x2, long y2, long xmin, long ymin, long xmax, long ymax)
+    /**
+     * @return start point of the clipped line
+     */
+    public Point getP1()
+    {
+        return p1;
+    }
+
+    /**
+     * @return end point of the clipped line
+     */
+    public Point getP2()
+    {
+        return p2;
+    }
+
+    /**
+     * see http://en.wikipedia.org/wiki/Cohen-Sutherland
+     */
+    private boolean cohenSutherland( long x1, long y1, long x2, long y2, long xmin, long ymin, long xmax, long ymax)
     {
         int outcode0, outcode1, outcodeOut;
@@ -94,12 +107,23 @@
     }
 
-    public Point getP1()
-    {
-        return p1;
-    }
-
-    public Point getP2()
-    {
-        return p2;
+    /**
+     * The outcode of the point.
+     * We cannot use Rectangle.outcode since it does not work with long ints.
+     */
+    private static int computeOutCode (long x, long y, long xmin, long ymin, long xmax, long ymax) {
+        int code = 0;
+        if (y > ymax) {
+            code |= OUT_TOP;
+        }
+        else if (y < ymin) {
+            code |= OUT_BOTTOM;
+        }
+        if (x > xmax) {
+            code |= OUT_RIGHT;
+        }
+        else if (x < xmin) {
+            code |= OUT_LEFT;
+        }
+        return code;
     }
 }
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 3562)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 3565)
@@ -54,4 +54,8 @@
     private final Collection<String> regionalNameOrder;
 
+    private static final double PHI = Math.toRadians(20);
+    private static final double cosPHI = Math.cos(PHI);
+    private static final double sinPHI = Math.sin(PHI);
+
     public MapPainter(MapPaintSettings settings, Graphics2D g, boolean inactive, NavigatableComponent nc, boolean virtual, double dist, double circum) {
         this.g = g;
@@ -85,6 +89,10 @@
 
         GeneralPath path = new GeneralPath();
+        GeneralPath arrows = new GeneralPath();
+        Rectangle bounds = g.getClipBounds();
+        bounds.grow(100, 100);                  // avoid arrow heads at the border
 
         Point lastPoint = null;
+        boolean initialMoveToNeeded = true;
         Iterator<Node> it = way.getNodes().iterator();
         while (it.hasNext()) {
@@ -92,12 +100,49 @@
             Point p = nc.getPoint(n);
             if(lastPoint != null) {
-                drawSegment(path, lastPoint, p, showHeadArrowOnly ? !it.hasNext() : showDirection, reversedDirection);
+                Point p1 = lastPoint;
+                Point p2 = p;
+
+                /**
+                 * Do custom clipping to work around openjdk bug. It leads to
+                 * drawing artefacts when zooming in a lot. (#4289, #4424)
+                 * (Looks like int overflow.)
+                 */
+                LineClip clip = new LineClip(p1, p2, bounds);
+                if (clip.execute()) {
+                    if (!p1.equals(clip.getP1())) {
+                        p1 = clip.getP1();
+                        path.moveTo(p1.x, p1.y);
+                    } else if (initialMoveToNeeded) {
+                        initialMoveToNeeded = false;
+                        path.moveTo(p1.x, p1.y);
+                    }
+                    p2 = clip.getP2();
+                    path.lineTo(p2.x, p2.y);
+
+                    /* draw arrow */
+                    if (showHeadArrowOnly ? !it.hasNext() : showDirection) {
+                        if (reversedDirection) {
+                            Point tmp = p1;
+                            p1 = p2;
+                            p2 = tmp;
+                        }
+                        final double l =  10. / p1.distance(p2);
+
+                        final double sx = l * (p1.x - p2.x);
+                        final double sy = l * (p1.y - p2.y);
+
+                        arrows.moveTo(p2.x, p2.y);
+                        arrows.lineTo (p2.x + (int) Math.round(cosPHI * sx - sinPHI * sy), p2.y + (int) Math.round(sinPHI * sx + cosPHI * sy));
+                        arrows.moveTo (p2.x + (int) Math.round(cosPHI * sx + sinPHI * sy), p2.y + (int) Math.round(- sinPHI * sx + cosPHI * sy));
+                        arrows.lineTo(p2.x, p2.y);
+                    }
+                }
             }
             lastPoint = p;
         }
-        displaySegments(path, color, width, dashed, dashedColor);
-    }
-
-    private void displaySegments(GeneralPath path, Color color, int width, float dashed[], Color dashedColor) {
+        displaySegments(path, arrows, color, width, dashed, dashedColor);
+    }
+
+    private void displaySegments(GeneralPath path, GeneralPath arrows, Color color, int width, float dashed[], Color dashedColor) {
         g.setColor(inactive ? inactiveColor : color);
         if (useStrokes) {
@@ -109,4 +154,5 @@
         }
         g.draw(path);
+        g.draw(arrows);
 
         if(!inactive && useStrokes && dashedColor != null) {
@@ -122,54 +168,9 @@
             }
             g.draw(path);
+            g.draw(arrows);
         }
 
         if(useStrokes) {
             g.setStroke(new BasicStroke());
-        }
-    }
-
-    private static final double PHI = Math.toRadians(20);
-    private static final double cosPHI = Math.cos(PHI);
-    private static final double sinPHI = Math.sin(PHI);
-
-    private void drawSegment(GeneralPath path, Point p1, Point p2, boolean showDirection, boolean reversedDirection) {
-        boolean drawIt = false;
-        if (Main.isOpenjdk) {
-            /**
-             * Work around openjdk bug. It leads to drawing artefacts when zooming in a lot. (#4289, #4424)
-             * (It looks like int overflow when clipping.) We do custom clipping.
-             */
-            Rectangle bounds = g.getClipBounds();
-            bounds.grow(100, 100);                  // avoid arrow heads at the border
-            LineClip clip = new LineClip();
-            drawIt = clip.cohenSutherland(p1.x, p1.y, p2.x, p2.y, bounds.x, bounds.y, bounds.x+bounds.width, bounds.y+bounds.height);
-            p1 = clip.getP1();
-            p2 = clip.getP2();
-        } else {
-            drawIt = isSegmentVisible(p1, p2);
-        }
-        if (drawIt) {
-            /* draw segment line */
-            path.moveTo(p1.x, p1.y);
-            path.lineTo(p2.x, p2.y);
-
-            /* draw arrow */
-            if (showDirection) {
-                Point q1 = p1;
-                Point q2 = p2;
-                if (reversedDirection) {
-                    q1 = p2;
-                    q2 = p1;
-                    path.moveTo(q2.x, q2.y);
-                }
-                final double l =  10. / q1.distance(q2);
-
-                final double sx = l * (q1.x - q2.x);
-                final double sy = l * (q1.y - q2.y);
-
-                path.lineTo (q2.x + (int) Math.round(cosPHI * sx - sinPHI * sy), q2.y + (int) Math.round(sinPHI * sx + cosPHI * sy));
-                path.moveTo (q2.x + (int) Math.round(cosPHI * sx + sinPHI * sy), q2.y + (int) Math.round(- sinPHI * sx + cosPHI * sy));
-                path.lineTo(q2.x, q2.y);
-            }
         }
     }
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/SimplePaintVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/SimplePaintVisitor.java	(revision 3562)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/SimplePaintVisitor.java	(revision 3565)
@@ -481,6 +481,6 @@
             Rectangle bounds = g.getClipBounds();
             bounds.grow(100, 100);                  // avoid arrow heads at the border
-            LineClip clip = new LineClip();
-            drawIt = clip.cohenSutherland(p1.x, p1.y, p2.x, p2.y, bounds.x, bounds.y, bounds.x+bounds.width, bounds.y+bounds.height);
+            LineClip clip = new LineClip(p1, p2, bounds);
+            drawIt = clip.execute();
             p1 = clip.getP1();
             p2 = clip.getP2();
