Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 3978)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 3979)
@@ -12,4 +12,5 @@
 import java.awt.Polygon;
 import java.awt.Rectangle;
+import java.awt.Shape;
 import java.awt.TexturePaint;
 import java.awt.font.FontRenderContext;
@@ -315,7 +316,16 @@
             gv.setGlyphTransform(i, trfm);
         }
-        g.setColor(text.color);
-        g.drawGlyphVector(gv, 0, 0);
-
+        if (text.haloRadius != null) {
+            Shape textOutline = gv.getOutline();
+            g.setStroke(new BasicStroke(2*text.haloRadius, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND));
+            g.setColor(text.haloColor);
+            g.draw(textOutline);
+            g.setStroke(new BasicStroke());
+            g.setColor(text.color);
+            g.fill(textOutline);
+        } else {
+            g.setColor(text.color);
+            g.drawGlyphVector(gv, 0, 0);
+        }
     }
 
@@ -489,9 +499,4 @@
             return;
 
-        if (inactive || n.isDisabled()) {
-            g.setColor(inactiveColor);
-        } else {
-            g.setColor(text.color);
-        }
         Font defaultFont = g.getFont();
         g.setFont(text.font);
@@ -538,5 +543,22 @@
             } else throw new AssertionError();
         }
-        g.drawString(s, x, y);
+        if (inactive || n.isDisabled()) {
+            g.setColor(inactiveColor);
+        } else {
+            g.setColor(text.color);
+        }
+        if (text.haloRadius != null) {
+            g.setStroke(new BasicStroke(2*text.haloRadius, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND));
+            g.setColor(text.haloColor);
+            FontRenderContext frc = g.getFontRenderContext();
+            GlyphVector gv = text.font.createGlyphVector(frc, s);
+            Shape textOutline = gv.getOutline(x, y);
+            g.draw(textOutline);
+            g.setStroke(new BasicStroke());
+            g.setColor(text.color);
+            g.fill(textOutline);
+        } else {
+            g.drawString(s, x, y);
+        }
         g.setFont(defaultFont);
     }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(revision 3978)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(revision 3979)
@@ -6,5 +6,4 @@
 import java.awt.BasicStroke;
 import java.awt.Color;
-import java.awt.Font;
 import java.awt.Stroke;
 
@@ -93,6 +92,6 @@
         public VerticalTextAlignment vAlign;
 
-        public NodeTextElement(String textKey, HorizontalTextAlignment hAlign, VerticalTextAlignment vAlign, Font font, int xOffset, int yOffset, Color color) {
-            super(textKey, font, xOffset, yOffset, color);
+        public NodeTextElement(TextElement text, HorizontalTextAlignment hAlign, VerticalTextAlignment vAlign) {
+            super(text);
             CheckParameterUtil.ensureParameterNotNull(hAlign);
             CheckParameterUtil.ensureParameterNotNull(vAlign);
@@ -192,5 +191,5 @@
                 vAlign = VerticalTextAlignment.BELOW;
             }
-            text = new NodeTextElement(te.textKey, hAlign, vAlign, te.font, te.xOffset, te.yOffset, te.color);
+            text = new NodeTextElement(te, hAlign, vAlign);
         }
         
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/TextElement.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/TextElement.java	(revision 3978)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/TextElement.java	(revision 3979)
@@ -10,4 +10,5 @@
 
 import org.openstreetmap.josm.tools.CheckParameterUtil;
+import org.openstreetmap.josm.tools.Utils;
 
 public class TextElement {
@@ -19,6 +20,8 @@
     public int yOffset;
     public Color color;
+    public Float haloRadius;
+    public Color haloColor;
 
-    public TextElement(String textKey, Font font, int xOffset, int yOffset, Color color) {
+    public TextElement(String textKey, Font font, int xOffset, int yOffset, Color color, Float haloRadius, Color haloColor) {
         CheckParameterUtil.ensureParameterNotNull(font);
         CheckParameterUtil.ensureParameterNotNull(color);
@@ -28,4 +31,16 @@
         this.yOffset = yOffset;
         this.color = color;
+        this.haloRadius = haloRadius;
+        this.haloColor = haloColor;
+    }
+
+    public TextElement(TextElement other) {
+        this.textKey = other.textKey;
+        this.font = other.font;
+        this.xOffset = other.xOffset;
+        this.yOffset = other.yOffset;
+        this.color = other.color;
+        this.haloColor = other.haloColor;
+        this.haloRadius = other.haloRadius;
     }
 
@@ -58,6 +73,21 @@
         
         Color color = c.get("text-color", defTextColor, Color.class);
-        
-        return new TextElement(textKey, font, (int) xOffset, - (int) yOffset, color);
+        float alpha = c.get("text-opacity", 1f, Float.class);
+        color = new Color(color.getRed(), color.getGreen(),
+                color.getBlue(), Utils.color_float2int(alpha));
+
+        Float haloRadius = c.get("text-halo-radius", null, Float.class);
+        if (haloRadius != null && haloRadius <= 0) {
+            haloRadius = null;
+        }
+        Color haloColor = null;
+        if (haloRadius != null) {
+            haloColor = c.get("text-halo-color", Utils.complement(color), Color.class);
+            float haloAlpha = c.get("text-halo-opacity", 1f, Float.class);
+            haloColor = new Color(haloColor.getRed(), haloColor.getGreen(),
+                    haloColor.getBlue(), Utils.color_float2int(haloAlpha));
+        }
+
+        return new TextElement(textKey, font, (int) xOffset, - (int) yOffset, color, haloRadius, haloColor);
     }
 
@@ -71,5 +101,7 @@
                 xOffset == other.xOffset &&
                 yOffset == other.yOffset &&
-                equal(color, other.color);
+                equal(color, other.color) &&
+                equal(haloRadius, other.haloRadius) &&
+                equal(haloColor, other.haloColor);
     }
 
@@ -82,4 +114,6 @@
         hash = 79 * hash + yOffset;
         hash = 79 * hash + color.hashCode();
+        hash = 79 * hash + (haloRadius != null ? Float.floatToIntBits(haloRadius) : 0);
+        hash = 79 * hash + (haloColor != null ? haloColor.hashCode() : 0);
         return hash;
     }
Index: trunk/src/org/openstreetmap/josm/tools/Utils.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 3978)
+++ trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 3979)
@@ -160,3 +160,6 @@
     }
 
+    public static Color complement(Color clr) {
+        return new Color(255 - clr.getRed(), 255 - clr.getGreen(), 255 - clr.getBlue(), clr.getAlpha());
+    }
 }
