Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 3879)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 3880)
@@ -14,5 +14,7 @@
 import java.awt.TexturePaint;
 import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
 import java.awt.font.LineMetrics;
+import java.awt.geom.AffineTransform;
 import java.awt.geom.GeneralPath;
 import java.awt.geom.Rectangle2D;
@@ -37,9 +39,9 @@
 import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.HorizontalTextAlignment;
 import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.Symbol;
-import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.TextElement;
+import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.NodeTextElement;
 import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.VerticalTextAlignment;
+import org.openstreetmap.josm.gui.mappaint.TextElement;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.LanguageInfo;
-import org.openstreetmap.josm.tools.Utils;
 
 public class MapPainter {
@@ -106,5 +108,5 @@
     }
 
-    public void drawWay(Way way, Color color, BasicStroke line, BasicStroke dashes, Color dashedColor, boolean showDirection,
+    public void drawWay(Way way, Color color, BasicStroke line, BasicStroke dashes, Color dashedColor, TextElement text, boolean showDirection,
             boolean reversedDirection, boolean showHeadArrowOnly) {
 
@@ -163,4 +165,5 @@
         }
         displaySegments(path, arrows, color, line, dashes, dashedColor);
+        drawTextOnPath(way, text);
     }
 
@@ -193,5 +196,99 @@
     }
 
-    public void drawNodeIcon(Node n, ImageIcon icon, float iconAlpha, boolean selected, boolean member, TextElement text) {
+    private void drawTextOnPath(Way way, TextElement text) {
+        if (text == null)
+            return;
+        String name = getAreaName(way);
+        if (name == null || name.equals(""))
+            return;
+
+        Polygon poly = new Polygon();
+        Point lastPoint = null;
+        Iterator<Node> it = way.getNodes().iterator();
+        double pathLength = 0;
+        int dx, dy;
+        while (it.hasNext()) {
+            Node n = it.next();
+            Point p = nc.getPoint(n);
+            poly.addPoint(p.x, p.y);
+
+            if(lastPoint != null) {
+                dx = p.x - lastPoint.x;
+                dy = p.y - lastPoint.y;
+                pathLength += Math.sqrt(dx*dx + dy*dy);
+            }
+            lastPoint = p;
+        }
+
+        FontMetrics fontMetrics = g.getFontMetrics(text.font); // if slow, use cache
+        Rectangle2D rec = fontMetrics.getStringBounds(name, g); // if slow, approximate by strlen()*maxcharbounds(font)
+
+        if (rec.getWidth() > pathLength)
+            return;
+
+        double t1 = (pathLength/2 - rec.getWidth()/2) / pathLength;
+        double t2 = (pathLength/2 + rec.getWidth()/2) / pathLength;
+
+        double[] p1 = pointAt(t1, poly, pathLength);
+        double[] p2 = pointAt(t2, poly, pathLength);
+
+        double angleOffset;
+        double offsetSign;
+        double tStart;
+
+        if (p1[0] < p2[0] &&
+            p1[2] < Math.PI/2 &&
+            p1[2] > -Math.PI/2) {
+            angleOffset = 0;
+            offsetSign = 1;
+            tStart = t1;
+        } else {
+            angleOffset = Math.PI;
+            offsetSign = -1;
+            tStart = t2;
+        }
+
+        FontRenderContext frc = g.getFontRenderContext();
+        GlyphVector gv = text.font.createGlyphVector(frc, name);
+
+        for (int i=0; i<gv.getNumGlyphs(); ++i) {
+            Rectangle2D rect = gv.getGlyphLogicalBounds(i).getBounds2D();
+            double t = tStart + offsetSign * (rect.getX() + rect.getWidth()/2) / pathLength;
+            double[] p = pointAt(t, poly, pathLength);
+            AffineTransform trfm = AffineTransform.getTranslateInstance(p[0] - rect.getX(), p[1]);
+            trfm.rotate(p[2]+angleOffset);
+            double off = -rect.getY() - rect.getHeight()/2 + text.yOffset;
+            trfm.translate(-rect.getWidth()/2, off);
+            gv.setGlyphTransform(i, trfm);
+        }
+        g.setColor(text.color);
+        g.drawGlyphVector(gv, 0, 0);
+
+    }
+
+    private double[] pointAt(double t, Polygon poly, double pathLength) {
+        double totalLen = t * pathLength;
+        double curLen = 0;
+        int dx, dy;
+        double segLen;
+
+        // Yes, it is ineffecient to iterate from the beginning for each glyph.
+        // Can be optimized if it turns out to be slow.
+        for (int i = 1; i < poly.npoints; ++i) {
+            dx = poly.xpoints[i] - poly.xpoints[i-1];
+            dy = poly.ypoints[i] - poly.ypoints[i-1];
+            segLen = Math.sqrt(dx*dx + dy*dy);
+            if (totalLen > curLen + segLen) {
+                curLen += segLen;
+                continue;
+            }
+            return new double[] {poly.xpoints[i-1]+(totalLen - curLen)/segLen*dx,
+                                 poly.ypoints[i-1]+(totalLen - curLen)/segLen*dy,
+                                 Math.atan2(dy, dx)};
+        }
+        return null;
+    }
+
+    public void drawNodeIcon(Node n, ImageIcon icon, float iconAlpha, boolean selected, boolean member, NodeTextElement text) {
         Point p = nc.getPoint(n);
         if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
@@ -211,5 +308,5 @@
     }
 
-    public void drawNodeSymbol(Node n, Symbol s, Color fillColor, Color strokeColor, TextElement text) {
+    public void drawNodeSymbol(Node n, Symbol s, Color fillColor, Color strokeColor, NodeTextElement text) {
         Point p = nc.getPoint(n);
         if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
@@ -253,5 +350,5 @@
      * @param color The color of the node.
      */
-    public void drawNode(Node n, Color color, int size, boolean fill, TextElement text) {
+    public void drawNode(Node n, Color color, int size, boolean fill, NodeTextElement text) {
         if (size > 1) {
             Point p = nc.getPoint(n);
@@ -274,5 +371,5 @@
     }
 
-    private void drawNodeText(Node n, TextElement text, Point p, int w_half, int h_half) {
+    private void drawNodeText(Node n, NodeTextElement text, Point p, int w_half, int h_half) {
         if (!isShowNames() || text == null)
             return;
@@ -345,10 +442,10 @@
     }
 
-    public void drawArea(Way w, Color color, BufferedImage fillImage, float fillImageAlpha, String name) {
+    public void drawArea(Way w, Color color, BufferedImage fillImage, float fillImageAlpha, TextElement text) {
         Polygon polygon = getPolygon(w);
-        drawArea(polygon, color, fillImage, fillImageAlpha, name);
-    }
-
-    protected void drawArea(Polygon polygon, Color color, BufferedImage fillImage, float fillImageAlpha, String name) {
+        drawArea(w, polygon, color, fillImage, fillImageAlpha, text);
+    }
+
+    protected void drawArea(OsmPrimitive osm, Polygon polygon, Color color, BufferedImage fillImage, float fillImageAlpha, TextElement text) {
 
         if (fillImage == null) {
@@ -366,5 +463,9 @@
         }
 
-        if (name != null) {
+        if (text != null && isShowNames()) {
+            String name = text.textKey == null ? getAreaName(osm) : osm.get(text.textKey);
+            if (name == null)
+                return;
+
             Rectangle pb = polygon.getBounds();
             FontMetrics fontMetrics = g.getFontMetrics(orderFont); // if slow, use cache
@@ -403,5 +504,5 @@
     }
 
-    public void drawArea(Relation r, Color color, BufferedImage fillImage, float fillImageAlpha, String name) {
+    public void drawArea(Relation r, Color color, BufferedImage fillImage, float fillImageAlpha, TextElement text) {
         Multipolygon multipolygon = new Multipolygon(nc);
         multipolygon.load(r);
@@ -412,5 +513,5 @@
                     continue;
                 }
-                drawArea(p, color, fillImage, fillImageAlpha, getAreaName(r));
+                drawArea(r, p, color, fillImage, fillImageAlpha, text);
             }
         }
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/AreaElemStyle.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/AreaElemStyle.java	(revision 3879)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/AreaElemStyle.java	(revision 3880)
@@ -26,6 +26,7 @@
     public BufferedImage fillImage;
     public float fillImageAlpha;
+    public TextElement text;
 
-    protected AreaElemStyle(Cascade c, Color color, BufferedImage fillImage, float fillImageAlpha) {
+    protected AreaElemStyle(Cascade c, Color color, BufferedImage fillImage, float fillImageAlpha, TextElement text) {
         super(c);
         CheckParameterUtil.ensureParameterNotNull(color);
@@ -33,4 +34,5 @@
         this.fillImage = fillImage;
         this.fillImageAlpha = fillImageAlpha;
+        this.text = text;
     }
 
@@ -73,7 +75,13 @@
             }
         }
+
+        TextElement text = null;
+        String textPos = c.get("text-position", null, String.class);
+        if (textPos == null || Utils.equal(textPos, "center")) {
+            text = TextElement.create(c);
+        }
         
         if (color != null)
-            return new AreaElemStyle(c, color, fillImage, fillImageAlpha);
+            return new AreaElemStyle(c, color, fillImage, fillImageAlpha, text);
         else
             return null;
@@ -90,6 +98,5 @@
                 }
             }
-            painter.drawArea((Way) osm, myColor, fillImage, fillImageAlpha,
-                    painter.isShowNames() ? painter.getAreaName(osm) : null);
+            painter.drawArea((Way) osm, myColor, fillImage, fillImageAlpha, text);
         } else if (osm instanceof Relation)
         {
@@ -100,6 +107,5 @@
                 }
             }
-            painter.drawArea((Relation) osm, myColor, fillImage, fillImageAlpha,
-                    painter.getAreaName(osm));
+            painter.drawArea((Relation) osm, myColor, fillImage, fillImageAlpha, text);
         }
     }
@@ -119,4 +125,6 @@
         if (fillImageAlpha != other.fillImageAlpha)
             return false;
+        if (!Utils.equal(text, other.text))
+            return false;
         return true;
     }
@@ -128,4 +136,5 @@
         hash = 61 * hash + (fillImage != null ? fillImage.hashCode() : 0);
         hash = 61 * hash + Float.floatToIntBits(fillImageAlpha);
+        hash = 61 * hash + (text != null ? text.hashCode() : 0);
         return hash;
     }
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java	(revision 3879)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java	(revision 3880)
@@ -2,7 +2,13 @@
 package org.openstreetmap.josm.gui.mappaint;
 
+import static org.openstreetmap.josm.tools.Utils.equal;
+
+import java.awt.Font;
+
+import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
 import org.openstreetmap.josm.data.osm.visitor.paint.MapPainter;
+import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction.RelativeFloat;
 
 abstract public class ElemStyle {
@@ -26,4 +32,40 @@
 
     public abstract void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, MapPainter painter, boolean selected, boolean member);
+
+    protected static Float getWidth(Cascade c, String key, Float relativeTo) {
+        Float width = c.get(key, null, Float.class, true);
+        if (width != null) {
+            if (width == -1f)
+                return (float) MapPaintSettings.INSTANCE.getDefaultSegmentWidth();
+            if (width > 0)
+                return width;
+        } else {
+            String width_key = c.get(key, null, String.class, true);
+            if (equal(width_key, "thinnest"))
+                return 0f;
+            else if (relativeTo != null) {
+                RelativeFloat width_rel = c.get(key, null, RelativeFloat.class, true);
+                if (width_rel != null)
+                    return relativeTo + width_rel.val;
+            }
+        }
+        return null;
+    }
+
+    protected static Font getFont(Cascade c) {
+        String name = c.get("font-family", Main.pref.get("mappaint.font", "Helvetica"), String.class);
+        float size = c.get("font-size", (float) Main.pref.getInteger("mappaint.fontsize", 8), Float.class);
+        int weight = Font.PLAIN;
+        String weightStr = c.get("font-wheight", null, String.class);
+        if (equal(weightStr, "bold")) {
+            weight = Font.BOLD;
+        }
+        int style = Font.PLAIN;
+        String styleStr = c.get("font-style", null, String.class);
+        if (equal(styleStr, "italic")) {
+            style = Font.ITALIC;
+        }
+        return new Font(name, weight | style, Math.round(size));
+    }
 
     @Override
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 3879)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 3880)
@@ -14,5 +14,4 @@
 import org.openstreetmap.josm.data.osm.visitor.paint.MapPainter;
 import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
-import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction.RelativeFloat;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -32,9 +31,10 @@
     public Color color;
     public Color dashesBackground;
+    public TextElement text;
     public float realWidth; // the real width of this line in meter
 
     private BasicStroke dashesLine;
 
-    protected LineElemStyle(Cascade c, BasicStroke line, Color color, BasicStroke dashesLine, Color dashesBackground, float realWidth) {
+    protected LineElemStyle(Cascade c, BasicStroke line, Color color, BasicStroke dashesLine, Color dashesBackground, TextElement text, float realWidth) {
         super(c);
         this.line = line;
@@ -42,13 +42,14 @@
         this.dashesLine = dashesLine;
         this.dashesBackground = dashesBackground;
+        this.text = text;
         this.realWidth = realWidth;
     }
 
     public static LineElemStyle createLine(Environment env) {
-        return createImpl(env, "");
+        return createImpl(env, false);
     }
 
     public static LineElemStyle createCasing(Environment env) {
-        LineElemStyle casing =  createImpl(env, "casing-");
+        LineElemStyle casing =  createImpl(env, true);
         if (casing != null) {
             casing.object_z_index = -1;
@@ -57,26 +58,22 @@
     }
 
-    private static LineElemStyle createImpl(Environment env, String prefix) {
+    private static LineElemStyle createImpl(Environment env, boolean casing) {
         Cascade c = env.getCascade();
-        Float width = c.get(prefix + "width", null, Float.class, true);
-        if (width != null) {
-            if (width == -1f) {
-                width = (float) MapPaintSettings.INSTANCE.getDefaultSegmentWidth();
-            }
-            if (width <= 0)
-                return null;
+        Cascade c_def = env.mc.getCascade("default");
+
+        String prefix = casing ? "casing-" : "";
+
+        Float width;
+        if (casing) {
+            Float widthOnDefault = getWidth(c_def, "width", null);
+            Float widthLine = getWidth(c, "width", widthOnDefault);
+            width = getWidth(c, "casing-width", widthLine);
         } else {
-            String width_key = c.get(prefix + "width", null, String.class, true);
-            if (equal(width_key, "thinnest")) {
-                width = 0f;
-            } else if (! equal(env.layer, "default")) {
-                RelativeFloat width_rel = c.get(prefix + "width", null, RelativeFloat.class, true);
-                if (width_rel != null) {
-                    width = env.mc.getCascade("default").get("width", 0f, Float.class) + width_rel.val;
-                } else
-                    return null;
-            } else
-                return null;
-        }
+            Float widthOnDefault = getWidth(c_def, "width", null);
+            width = getWidth(c, "width", widthOnDefault);
+        }
+
+        if (width == null)
+            return null;
 
         float realWidth = c.get(prefix + "real-width", 0f, Float.class);
@@ -178,5 +175,13 @@
         }
 
-        return new LineElemStyle(c, line, color, dashesLine, dashesBackground, realWidth);
+        TextElement text = null;
+        if (!casing) {
+            String textPos = c.get("text-position", null, String.class);
+            if (textPos == null || equal(textPos, "line")) {
+                text = TextElement.create(c);
+            }
+        }
+
+        return new LineElemStyle(c, line, color, dashesLine, dashesBackground, text, realWidth);
     }
 
@@ -222,5 +227,5 @@
         }
 
-        painter.drawWay(w, markColor != null ? markColor : color, myLine, myDashLine, myDashedColor, showDirection,
+        painter.drawWay(w, markColor != null ? markColor : color, myLine, myDashLine, myDashedColor, text, showDirection,
                 selected ? false : reversedDirection, showOnlyHeadArrowOnly);
 
@@ -249,4 +254,5 @@
                 equal(dashesLine, other.dashesLine) &&
                 equal(dashesBackground, other.dashesBackground) &&
+                equal(text, other.text) &&
                 realWidth == other.realWidth;
     }
@@ -259,4 +265,5 @@
         hash = 29 * hash + (dashesLine != null ? dashesLine.hashCode() : 0);
         hash = 29 * hash + (dashesBackground != null ? dashesBackground.hashCode() : 0);
+        hash = 29 * hash + (text != null ? text.hashCode() : 0);
         hash = 29 * hash + Float.floatToIntBits(realWidth);
         return hash;
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(revision 3879)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(revision 3880)
@@ -18,5 +18,4 @@
 import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
 import org.openstreetmap.josm.data.osm.visitor.paint.MapPainter;
-import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
@@ -31,5 +30,5 @@
     public int iconAlpha;
     public Symbol symbol;
-    public TextElement text;
+    public NodeTextElement text;
 
     private ImageIcon disabledIcon;
@@ -89,53 +88,35 @@
     }
 
-    public static class TextElement {
-        public String textKey;
+    public static class NodeTextElement extends TextElement {
         public HorizontalTextAlignment hAlign;
         public VerticalTextAlignment vAlign;
-        public Font font;
-        public int xOffset;
-        public int yOffset;
-        public Color color;
-
-        public TextElement(String textKey, HorizontalTextAlignment hAlign, VerticalTextAlignment vAlign, Font font, int xOffset, int yOffset, Color color) {
+
+        public NodeTextElement(String textKey, HorizontalTextAlignment hAlign, VerticalTextAlignment vAlign, Font font, int xOffset, int yOffset, Color color) {
+            super(textKey, font, xOffset, yOffset, color);
             CheckParameterUtil.ensureParameterNotNull(hAlign);
             CheckParameterUtil.ensureParameterNotNull(vAlign);
-            CheckParameterUtil.ensureParameterNotNull(font);
-            CheckParameterUtil.ensureParameterNotNull(color);
-            this.textKey = textKey;
             this.hAlign = hAlign;
             this.vAlign = vAlign;
-            this.font = font;
-            this.xOffset = xOffset;
-            this.yOffset = yOffset;
-            this.color = color;
         }
 
         @Override
         public boolean equals(Object obj) {
+            if (!super.equals(obj))
+                return false;
             if (obj == null || getClass() != obj.getClass())
                 return false;
-            final TextElement other = (TextElement) obj;
-            return  equal(textKey, other.textKey) &&
-                    hAlign == other.hAlign &&
-                    vAlign == other.vAlign &&
-                    equal(font, other.font) &&
-                    xOffset == other.xOffset &&
-                    yOffset == other.yOffset &&
-                    equal(color, other.color);
+            final NodeTextElement other = (NodeTextElement) obj;
+            return hAlign == other.hAlign &&
+                    vAlign == other.vAlign;
         }
 
         @Override
         public int hashCode() {
-            int hash = 3;
-            hash = 79 * hash + (textKey != null ? textKey.hashCode() : 0);
-            hash = 79 * hash + hAlign.hashCode();
-            hash = 79 * hash + vAlign.hashCode();
-            hash = 79 * hash + font.hashCode();
-            hash = 79 * hash + xOffset;
-            hash = 79 * hash + yOffset;
-            hash = 79 * hash + color.hashCode();
+            int hash = super.hashCode();
+            hash = 97 * hash + hAlign.hashCode();
+            hash = 97 * hash + vAlign.hashCode();
             return hash;
         }
+
     }
     
@@ -147,5 +128,5 @@
     }
 
-    protected NodeElemStyle(Cascade c, ImageIcon icon, int iconAlpha, Symbol symbol, TextElement text) {
+    protected NodeElemStyle(Cascade c, ImageIcon icon, int iconAlpha, Symbol symbol, NodeTextElement text) {
         super(c);
         this.icon = icon;
@@ -179,11 +160,7 @@
             return null;
 
-        TextElement text = null;
-        String textStr = c.get("text", null, String.class);
-        if (textStr != null) {
-            String textKey = null;
-            if (!"auto".equalsIgnoreCase(textStr)) {
-                textKey = textStr;
-            }
+        NodeTextElement text = null;
+        TextElement te = TextElement.create(c);
+        if (te != null) {
             HorizontalTextAlignment hAlign = HorizontalTextAlignment.RIGHT;
             String hAlignStr = c.get("text-anchor-horizontal", null, String.class);
@@ -208,21 +185,5 @@
                 vAlign = VerticalTextAlignment.BELOW;
             }
-            String name = c.get("font-family", Main.pref.get("mappaint.font", "Helvetica"), String.class);
-            float size = c.get("font-size", (float) Main.pref.getInteger("mappaint.fontsize", 8), Float.class);
-            int weight = Font.PLAIN;
-            String weightStr = c.get("font-wheight", null, String.class);
-            if (equal(weightStr, "bold")) {
-                weight = Font.BOLD;
-            }
-            int style = Font.PLAIN;
-            String styleStr = c.get("font-style", null, String.class);
-            if (equal(styleStr, "italic")) {
-                style = Font.ITALIC;
-            }
-            Font font = new Font(name, weight | style, Math.round(size));
-            int xOffset = c.get("text-offset-x", 0f, Float.class).intValue();
-            int yOffset = c.get("text-offset-y", 0f, Float.class).intValue();
-            Color color = c.get("text-color", PaintColors.TEXT.get(), Color.class);
-            text = new TextElement(textKey, hAlign, vAlign, font, xOffset, yOffset, color);
+            text = new NodeTextElement(te.textKey, hAlign, vAlign, te.font, te.xOffset, te.yOffset, te.color);
         }
         
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/TextElement.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/TextElement.java	(revision 3880)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/TextElement.java	(revision 3880)
@@ -0,0 +1,69 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.mappaint;
+
+import static org.openstreetmap.josm.tools.Utils.equal;
+
+import java.awt.Color;
+import java.awt.Font;
+
+import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
+import org.openstreetmap.josm.tools.CheckParameterUtil;
+
+public class TextElement {
+    public String textKey;
+    public Font font;
+    public int xOffset;
+    public int yOffset;
+    public Color color;
+
+    public TextElement(String textKey, Font font, int xOffset, int yOffset, Color color) {
+        CheckParameterUtil.ensureParameterNotNull(font);
+        CheckParameterUtil.ensureParameterNotNull(color);
+        this.textKey = textKey;
+        this.font = font;
+        this.xOffset = xOffset;
+        this.yOffset = yOffset;
+        this.color = color;
+    }
+
+    public static TextElement create(Cascade c) {
+        String textStr = c.get("text", null, String.class);
+        if (textStr == null)
+            return null;
+
+        String textKey = null;
+        if (!"auto".equalsIgnoreCase(textStr)) {
+            textKey = textStr;
+        }
+
+        Font font = ElemStyle.getFont(c);
+        int xOffset = c.get("text-offset-x", 0f, Float.class).intValue();
+        int yOffset = -c.get("text-offset-y", 0f, Float.class).intValue();
+        Color color = c.get("text-color", PaintColors.TEXT.get(), Color.class);
+        return new TextElement(textKey, font, xOffset, yOffset, color);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+        final TextElement other = (TextElement) obj;
+        return  equal(textKey, other.textKey) &&
+                equal(font, other.font) &&
+                xOffset == other.xOffset &&
+                yOffset == other.yOffset &&
+                equal(color, other.color);
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 3;
+        hash = 79 * hash + (textKey != null ? textKey.hashCode() : 0);
+        hash = 79 * hash + font.hashCode();
+        hash = 79 * hash + xOffset;
+        hash = 79 * hash + yOffset;
+        hash = 79 * hash + color.hashCode();
+        return hash;
+    }
+
+}
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java	(revision 3879)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java	(revision 3880)
@@ -191,4 +191,5 @@
             }
 
+            @SuppressWarnings("unchecked")
             public boolean equal(Object a, Object b) {
                 // make sure the casts are done in a meaningful way, so
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java	(revision 3879)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java	(revision 3880)
@@ -49,5 +49,5 @@
             return true;
         if (base.equals("area")) {
-            if (osm instanceof Way && ((Way)osm).isClosed())
+            if (osm instanceof Way)
                 return true;
             if (osm instanceof Relation && ((Relation) osm).isMultipolygon())
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/xml/XmlStyleSource.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/xml/XmlStyleSource.java	(revision 3879)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/xml/XmlStyleSource.java	(revision 3880)
@@ -350,4 +350,6 @@
             if (p.area != null) {
                 def.putOrClear("fill-color", p.area.color);
+                def.putOrClear("text-position", "center");
+                def.putOrClear("text", "auto");
                 def.remove("fill-image");
             }
