Index: trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 1262)
+++ trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 1263)
@@ -39,8 +39,24 @@
     public Map<String, String> keys;
 
-    /**
-     * The key/value list for this primitive.
-     */
+    /* mappaint data */
+    public ElemStyle mappaintStyle = null;
+    public boolean isMappaintArea = false;
+    public Integer mappaintVisibleCode = 0;
+    public Integer mappaintDrawnCode = 0;
+    public Integer mappaintDrawnAreaCode = 0;
     public Collection<String> errors;
+
+    public void putError(String text, Boolean isError)
+    {
+        if(errors == null)
+            errors = new ArrayList<String>();
+        String s = isError ? tr("Error: {0}", text) : tr("Warning: {0}", text);
+        errors.add(s);
+    }
+    public void clearErrors()
+    {
+        errors = null;
+    }
+    /* end of mappaint data */
 
     /**
@@ -140,9 +156,4 @@
     private static Collection<String> directionKeys = null;
 
-	
-    /* mappaint style cache */
-    public ElemStyle mappaintStyle = null;
-    public boolean isMappaintArea = false;
-	
     /**
      * Implementation of the visitor scheme. Subclasses have to call the correct
@@ -331,15 +342,3 @@
         }
     }
-
-    public void putError(String text, Boolean isError)
-    {
-        if(errors == null)
-            errors = new ArrayList<String>();
-        String s = isError ? tr("Error: {0}", text) : tr("Warning: {0}", text);
-        errors.add(s);
-    }
-    public void clearErrors()
-    {
-        errors = null;
-    }
 }
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 1262)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 1263)
@@ -40,4 +40,5 @@
     protected boolean fillAreas;
     protected boolean drawMultipolygon;
+    protected boolean showName;
     protected int fillAlpha;
     protected Color untaggedColor;
@@ -51,11 +52,14 @@
     protected String regionalNameOrder[];
     protected Boolean selectedCall;
-    protected Collection<OsmPrimitive> alreadyDrawn;
-    protected Collection<Way> alreadyDrawnAreas;
     protected Boolean useStyleCache;
-    
+    private static int paintid = 0;
+    private static int viewid = 0;
+
     protected int profilerVisibleNodes;
     protected int profilerVisibleWays;
     protected int profilerVisibleAreas;
+    protected int profilerSegments;
+    protected int profilerVisibleSegments;
+    protected boolean profilerOmitDraw;
 
     protected boolean isZoomOk(ElemStyle e) {
@@ -105,10 +109,18 @@
         // check, if the node is visible at all
         Point p = nc.getPoint(n.eastNorth);
-        if ((!selectedCall && n.selected) || (p.x < 0) || (p.y < 0)
-        || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
-        
+        if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight()))
+        {
+            n.mappaintVisibleCode = viewid;
+            return;
+        }
+        n.mappaintVisibleCode = 0;
+
         profilerVisibleNodes++;
         
         IconElemStyle nodeStyle = (IconElemStyle)getPrimitiveStyle(n);
+
+        if(profilerOmitDraw)
+            return;
+            
         if (nodeStyle != null && isZoomOk(nodeStyle))
             drawNode(n, nodeStyle.icon, nodeStyle.annotate, n.selected);
@@ -126,16 +138,27 @@
      */
     public void visit(Way w) {
-        if(w.nodes.size() < 2 && (!selectedCall && w.selected))
+        if(w.nodes.size() < 2)
+        {
+            w.mappaintVisibleCode = viewid;
             return;
+        }
 
         // check, if the way is visible at all
         Polygon polygon = getPolygon(w);
         if(!isPolygonVisible(polygon))
+        {
+            w.mappaintVisibleCode = viewid;
             return;
-            
+        }
+
         ElemStyle wayStyle = getPrimitiveStyle(w);
 
         if(!isZoomOk(wayStyle))
+        {
+            w.mappaintVisibleCode = viewid;
             return;
+        }
+
+        w.mappaintVisibleCode = 0;
 
         if(wayStyle==null)
@@ -143,5 +166,6 @@
             // way without style
             profilerVisibleWays++;
-            drawWay(w, null, untaggedColor, w.selected);
+            if(!profilerOmitDraw)
+                drawWay(w, null, untaggedColor, w.selected);
         }
         else if(wayStyle instanceof LineElemStyle)
@@ -149,15 +173,19 @@
             // way with line style
             profilerVisibleWays++;
-            drawWay(w, (LineElemStyle)wayStyle, untaggedColor, w.selected);
+            if(!profilerOmitDraw)
+                drawWay(w, (LineElemStyle)wayStyle, untaggedColor, w.selected);
         }
         else if (wayStyle instanceof AreaElemStyle)
         {
             // way with area style
-            if (fillAreas)
-            {
-                profilerVisibleAreas++;
-                drawArea(polygon, w.selected ? selectedColor : ((AreaElemStyle)wayStyle).color);
-            }
-            drawWay(w, ((AreaElemStyle)wayStyle).line, ((AreaElemStyle)wayStyle).color, w.selected);
+            if(!profilerOmitDraw)
+            {
+                if (fillAreas)
+                {
+                    profilerVisibleAreas++;
+                    drawArea(polygon, w.selected ? selectedColor : ((AreaElemStyle)wayStyle).color);
+                }
+                drawWay(w, ((AreaElemStyle)wayStyle).line, ((AreaElemStyle)wayStyle).color, w.selected);
+            }
         }
     }
@@ -360,5 +388,4 @@
                     drawSelected(m.member, styles != null ? styles.get(m.member)
                     : null, true, true);
-                alreadyDrawn.add(m.member);
             }
         }
@@ -390,25 +417,29 @@
                 drawNode((Node)osm, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
         }
+        osm.mappaintDrawnCode = paintid;
     }
 
     public void visit(Relation r) {
+   
+        r.mappaintVisibleCode = 0;
+        /* TODO implement visible handling for relations too */
+
+        // TODO: is it possible to do this like the nodes/ways code?
+        if(profilerOmitDraw)
+            return;
+
         // draw multipolygon relations including their ways
         // other relations are only drawn when selected
-        if(r.selected)
-        {
-            if(selectedCall)
-            {
-                for (RelationMember m : r.members)
-                {
-                    /* second call - draw nodes */
-                    if (m.member != null && !m.member.incomplete && !m.member.deleted
-                    && m.member instanceof Node)
-                    {
-                        drawSelected(m.member, styles != null ? styles.get(m.member) : null, true, true);
-                        alreadyDrawn.add(m.member);
-                    }
-                }
-                return;
-            }
+        if(r.selected && selectedCall)
+        {
+            for (RelationMember m : r.members)
+            {
+                if (m.member != null && !m.member.incomplete && !m.member.deleted
+                && m.member instanceof Node)
+                {
+                    drawSelected(m.member, styles != null ? styles.get(m.member) : null, true, true);
+                }
+            }
+            return;
         }
         if (!drawMultipolygon || r.keys == null || !"multipolygon".equals(r.keys.get("type")))
@@ -429,5 +460,5 @@
         for (RelationMember m : r.members)
         {
-            if(m.member == null) /* Should not happen, must be a bug elsewhere */
+            if(m.member == null) 
                 r.putError(tr("Empty member in relation."), true);
             else if(m.member.deleted)
@@ -462,5 +493,4 @@
                 else
                 {
-                    /* nodes drawn on second call */
                     r.putError(tr("Non-Way ''{0}'' in multipolygon.",
                     m.member.getName()), true);
@@ -470,6 +500,4 @@
 
         ElemStyle wayStyle = styles != null ? styles.get(r) : null;
-        /* find one wayStyle, prefer the style from Relation or take the first
-        one of outer rings */
         if(styles != null && (wayStyle == null || !(wayStyle instanceof AreaElemStyle)))
         {
@@ -486,5 +514,4 @@
             Collection<Way> join = new LinkedList<Way>();
 
-            /* parse all outer rings and join them */
             for (Way w : outer)
             {
@@ -498,5 +525,4 @@
             }
 
-            /* parse all inner rings and join them */
             join.clear();
             for (Way w : inner)
@@ -516,5 +542,5 @@
                 r.getName()), true);
             }
-            else if(zoomok) /* draw */
+            else if(zoomok) 
             {
                 class PolyData {
@@ -540,7 +566,7 @@
                                 --contains;
                         }
-                        if(contains == 0) return 1; /* inside */
-                        if(contains == p.npoints) return 0; /* outside */
-                        return 2; /* mixed */
+                        if(contains == 0) return 1; 
+                        if(contains == p.npoints) return 0; 
+                        return 2; 
                     }
                     public void addInner(Polygon p)
@@ -627,5 +653,5 @@
                         || r.selected);
                     }
-                    alreadyDrawn.add(wInner);
+                    wInner.mappaintDrawnCode = paintid;
                 }
                 else
@@ -635,5 +661,4 @@
                         drawSelected(wInner, innerStyle,
                         !wayStyle.equals(innerStyle), wInner.selected);
-                        alreadyDrawn.add(wInner);
                     }
                     if(wayStyle.equals(innerStyle))
@@ -642,5 +667,5 @@
                         wInner.getName()), false);
                         if(!r.selected)
-                            alreadyDrawnAreas.add(wInner);
+                            wInner.mappaintDrawnAreaCode = paintid;
                     }
                 }
@@ -657,5 +682,5 @@
                         || r.selected);
                     }
-                    alreadyDrawn.add(wOuter);
+                    wOuter.mappaintDrawnCode = paintid;
                 }
                 else
@@ -670,8 +695,7 @@
                     {
                         drawSelected(wOuter, outerStyle, false, false);
-                        alreadyDrawn.add(wOuter);
-                    }
-//                    else if(outerStyle instanceof AreaElemStyle)
-                        alreadyDrawnAreas.add(wOuter);
+                    }
+                    else if(outerStyle instanceof AreaElemStyle)
+                        wOuter.mappaintDrawnAreaCode = paintid;
                 }
             }
@@ -705,12 +729,15 @@
         int w = icon.getIconWidth(), h=icon.getIconHeight();
         icon.paintIcon ( Main.map.mapView, g, p.x-w/2, p.y-h/2 );
-        String name = getNodeName(n);
-        if (name!=null && annotate)
-        {
-            g.setColor(textColor);
-            Font defaultFont = g.getFont();
-            g.setFont (orderFont);
-            g.drawString (name, p.x+w/2+2, p.y+h/2+2);
-            g.setFont(defaultFont);
+        if(showName)
+        {
+            String name = getNodeName(n);
+            if (name!=null && annotate)
+            {
+                g.setColor(textColor);
+                Font defaultFont = g.getFont();
+                g.setFont (orderFont);
+                g.drawString (name, p.x+w/2+2, p.y+h/2+2);
+                g.setFont(defaultFont);
+            }
         }
         if (selected)
@@ -733,4 +760,5 @@
 
     private void drawSeg(Node n1, Node n2, Color col, boolean showDirection, int width, boolean dashed) {
+        profilerSegments++;
         if (col != currentColor || width != currentWidth || dashed != currentDashed) {
             displaySegments(col, width, dashed);
@@ -742,4 +770,5 @@
             return;
         }
+        profilerVisibleSegments++;
         currentPath.moveTo(p1.x, p1.y);
         currentPath.lineTo(p2.x, p2.y);
@@ -797,12 +826,15 @@
                 g.drawRect(p.x - radius, p.y - radius, size, size);
 
-            String name = getNodeName(n);
-            if (name!=null /* && annotate */)
-            {
-                g.setColor(textColor);
-                Font defaultFont = g.getFont();
-                g.setFont (orderFont);
-                g.drawString (name, p.x+radius+2, p.y+radius+2);
-                g.setFont(defaultFont);
+            if(showName)
+            {
+                String name = getNodeName(n);
+                if (name!=null /* && annotate */)
+                {
+                    g.setColor(textColor);
+                    Font defaultFont = g.getFont();
+                    g.setFont (orderFont);
+                    g.drawString (name, p.x+radius+2, p.y+radius+2);
+                    g.setFont(defaultFont);
+                }
             }
         }
@@ -820,7 +852,10 @@
 
         boolean profiler = Main.pref.getBoolean("mappaint.profiler",false);
+        profilerOmitDraw = Main.pref.getBoolean("mappaint.profiler.omitdraw",false);
+        
         useStyleCache = Main.pref.getBoolean("mappaint.cache",true);
         fillAreas = Main.pref.getBoolean("mappaint.fillareas", true);
         fillAlpha = Math.min(255, Math.max(0, Integer.valueOf(Main.pref.getInteger("mappaint.fillalpha", 50))));
+        showName = Main.pref.getBoolean("mappaint.showname", true);
 
         long profilerStart = java.lang.System.currentTimeMillis();
@@ -838,16 +873,18 @@
         circum = Main.map.mapView.getScale()*100*Main.proj.scaleFactor()*40041455; // circumference of the earth in meter
         styles = MapPaintStyles.getStyles().getStyleSet();
-        drawMultipolygon = Main.pref.getBoolean("mappaint.multipolygon",false);
+        drawMultipolygon = Main.pref.getBoolean("mappaint.multipolygon",true);
         orderFont = new Font(Main.pref.get("mappaint.font","Helvetica"), Font.PLAIN, Main.pref.getInteger("mappaint.fontsize", 8));
         String currentLocale = Locale.getDefault().getLanguage();
         regionalNameOrder = Main.pref.get("mappaint.nameOrder", "name:"+currentLocale+";name;int_name;ref;operator;brand").split(";");
 
-        alreadyDrawn = new LinkedList<OsmPrimitive>();
-        alreadyDrawnAreas = new LinkedList<Way>();
         selectedCall = false;
-        
+        ++paintid;
+        viewid = nc.getViewID();
+
         profilerVisibleNodes = 0;
         profilerVisibleWays = 0;
         profilerVisibleAreas = 0;
+        profilerSegments = 0;
+        profilerVisibleSegments = 0;
 
         if(profiler)
@@ -864,5 +901,5 @@
             for (final Relation osm : data.relations)
             {
-                if(!osm.deleted && !osm.incomplete)
+                if(!osm.deleted && !osm.incomplete && osm.mappaintVisibleCode != viewid)
                 {
                     osm.visit(this);
@@ -873,5 +910,5 @@
             if(profiler)
             {
-                System.out.format("Relations: %4dms, n=%5d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
+                System.out.format("Relations: %4dms, calls=%5d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
                 profilerLast = java.lang.System.currentTimeMillis();
             }
@@ -881,9 +918,8 @@
             for (final Way osm : data.ways)
             {
-                //if (!osm.incomplete && !osm.deleted && !alreadyDrawn.contains(osm))
-                if (!osm.incomplete && !osm.deleted)
-                {
-                    //if(styles.isArea((Way)osm) && !alreadyDrawnAreas.contains(osm))
-                    if(isPrimitiveArea(osm))
+                if (!osm.incomplete && !osm.deleted
+                && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid)
+                {
+                    if(isPrimitiveArea(osm) && osm.mappaintDrawnAreaCode != paintid)
                     {
                         osm.visit(this);
@@ -893,9 +929,8 @@
                 }
             }
-            alreadyDrawnAreas = null;
 
             if(profiler)
             {
-                System.out.format("Areas    : %4dms, n=%5d, visible=%d\n",
+                System.out.format("Areas    : %4dms, calls=%5d, visible=%d\n",
                     (java.lang.System.currentTimeMillis()-profilerLast), profilerN, profilerVisibleAreas);
                 profilerLast = java.lang.System.currentTimeMillis();
@@ -913,5 +948,5 @@
             if(profiler)
             {
-                System.out.format("Ways     : %4dms, n=%5d, visible=%d\n",
+                System.out.format("Ways     : %4dms, calls=%5d, visible=%d\n",
                     (java.lang.System.currentTimeMillis()-profilerLast), profilerN, profilerVisibleWays);
                 profilerLast = java.lang.System.currentTimeMillis();
@@ -923,5 +958,6 @@
             profilerN = 0;
             for (final OsmPrimitive osm : data.ways)
-                if (!osm.incomplete && !osm.deleted && !osm.selected)
+                if (!osm.incomplete && !osm.deleted && !osm.selected
+                && osm.mappaintVisibleCode != viewid )
                 {
                     osm.visit(this);
@@ -931,5 +967,5 @@
             if(profiler)
             {
-                System.out.format("Ways     : %4dms, n=%5d, visible=%d\n", 
+                System.out.format("Ways     : %4dms, calls=%5d, visible=%d\n",
                     (java.lang.System.currentTimeMillis()-profilerLast), profilerN, profilerVisibleWays);
                 profilerLast = java.lang.System.currentTimeMillis();
@@ -941,7 +977,6 @@
         profilerN = 0;
         for (final OsmPrimitive osm : data.getSelected()) {
-            if (!osm.incomplete && !osm.deleted
-            //&& !(osm instanceof Node) && !alreadyDrawn.contains(osm))
-            && !(osm instanceof Node))
+            if (!osm.incomplete && !osm.deleted && !(osm instanceof Node)
+            && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid)
             {
                 osm.visit(this);
@@ -952,5 +987,5 @@
         if(profiler)
         {
-            System.out.format("Selected : %4dms, n=%5d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
+            System.out.format("Selected : %4dms, calls=%5d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
             profilerLast = java.lang.System.currentTimeMillis();
         }
@@ -967,6 +1002,6 @@
         profilerN = 0;
         for (final OsmPrimitive osm : data.nodes)
-            //if (!osm.incomplete && !osm.deleted && !alreadyDrawn.contains(osm))
-            if (!osm.incomplete && !osm.deleted)
+            if (!osm.incomplete && !osm.deleted
+            && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid)
             {
                 osm.visit(this);
@@ -976,10 +1011,8 @@
         if(profiler)
         {
-            System.out.format("Nodes    : %4dms, n=%5d, visible=%d\n",
+            System.out.format("Nodes    : %4dms, calls=%5d, visible=%d\n",
                 (java.lang.System.currentTimeMillis()-profilerLast), profilerN, profilerVisibleNodes);
             profilerLast = java.lang.System.currentTimeMillis();
         }
-
-        alreadyDrawn = null;
 
         /*** VIRTUAL  ***/
@@ -989,7 +1022,10 @@
             currentColor = nodeColor;
             for (final OsmPrimitive osm : data.ways)
-                if (!osm.incomplete && !osm.deleted)
-                {
-                    visitVirtual((Way)osm);
+                if (!osm.incomplete && !osm.deleted
+                && osm.mappaintVisibleCode != viewid )
+                {
+                    // TODO: move this into the SimplePaint code?
+                    if(!profilerOmitDraw)
+                        visitVirtual((Way)osm);
                     profilerN++;
                 }
@@ -997,5 +1033,5 @@
             if(profiler)
             {
-                System.out.format("Virtual  : %4dms, n=%5d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
+                System.out.format("Virtual  : %4dms, calls=%5d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
                 profilerLast = java.lang.System.currentTimeMillis();
             }
@@ -1011,4 +1047,5 @@
         if(profiler)
         {
+            System.out.format("Segments :         calls=%5d, visible=%d\n", profilerSegments, profilerVisibleSegments);
             System.out.format("All      : %4dms\n", (profilerLast-profilerStart));
         }
Index: trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 1262)
+++ trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 1263)
@@ -67,4 +67,16 @@
                 return zoom;
         return 32;
+    }
+
+    /**
+     * Return a ID which is unique as long as viewport dimensions are the same
+     */
+    public Integer getViewID()
+    {
+        String x = center.east() + "_" + center.north() + "_" + scale + "_" +
+        getWidth() + "_" + getHeight();
+        java.util.zip.CRC32 id = new java.util.zip.CRC32();
+        id.update(x.getBytes());
+        return new Long(id.getValue()).intValue();
     }
 
