Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 11721)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 11722)
@@ -75,7 +75,9 @@
 import org.openstreetmap.josm.gui.mappaint.styleelement.MapImage;
 import org.openstreetmap.josm.gui.mappaint.styleelement.NodeElement;
+import org.openstreetmap.josm.gui.mappaint.styleelement.PositionForAreaStrategy;
 import org.openstreetmap.josm.gui.mappaint.styleelement.RepeatImageElement.LineImageAlignment;
 import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement;
 import org.openstreetmap.josm.gui.mappaint.styleelement.Symbol;
+import org.openstreetmap.josm.gui.mappaint.styleelement.TextElement;
 import org.openstreetmap.josm.gui.mappaint.styleelement.TextLabel;
 import org.openstreetmap.josm.tools.CompositeList;
@@ -400,10 +402,6 @@
     protected void drawArea(OsmPrimitive osm, Path2D.Double path, Color color,
             MapImage fillImage, Float extent, Path2D.Double pfClip, boolean disabled, TextLabel text) {
-
-        Shape area = path.createTransformedShape(mapState.getAffineTransform());
-
-        if (color.getAlpha() == 0) {
-            // skip drawing
-        } else if (!isOutlineOnly) {
+        if (!isOutlineOnly && color.getAlpha() != 0) {
+            Shape area = path.createTransformedShape(mapState.getAffineTransform());
             g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
             if (fillImage == null) {
@@ -451,9 +449,9 @@
         }
 
-        drawAreaText(osm, text, area);
-    }
-
-    private void drawAreaText(OsmPrimitive osm, TextLabel text, Shape area) {
-        if (text != null && isShowNames()) {
+        drawAreaText(osm, text, path);
+    }
+
+    private void drawAreaText(OsmPrimitive osm, TextLabel text, Path2D.Double path) {
+        if (text != null && isShowNames() && isAreaVisible(path)) {
             // abort if we can't compose the label to be rendered
             if (text.labelCompositionStrategy == null) return;
@@ -461,8 +459,9 @@
             if (name == null || name.isEmpty()) return;
 
+            Shape area = path.createTransformedShape(mapState.getAffineTransform());
             FontMetrics fontMetrics = g.getFontMetrics(orderFont); // if slow, use cache
             Rectangle2D nb = fontMetrics.getStringBounds(name, g); // if slow, approximate by strlen()*maxcharbounds(font)
 
-            Rectangle centeredNBounds = findLabelPlacement(area, nb);
+            Rectangle2D centeredNBounds = text.getLabelPositionSteategy().findLabelPlacement(area, nb);
             if (centeredNBounds != null) {
                 Font defaultFont = g.getFont();
@@ -475,75 +474,4 @@
             }
         }
-    }
-
-    /**
-     * Finds the correct position of a label / icon inside the area.
-     * @param area The area to search in
-     * @param nb The bounding box of the thing we are searching a place for.
-     * @return The position as rectangle with the same dimension as nb. <code>null</code> if none was found.
-     */
-    private Rectangle findLabelPlacement(Shape area, Rectangle2D nb) {
-        // Using the Centroid is Nicer for buildings like: +--------+
-        // but this needs to be fast.  As most houses are  |   42   |
-        // boxes anyway, the center of the bounding box    +---++---+
-        // will have to do.                                    ++
-        // Centroids are not optimal either, just imagine a U-shaped house.
-
-        Rectangle pb = area.getBounds();
-
-        // quick check to see if label box is smaller than primitive box
-        if (pb.width < nb.getWidth() || pb.height < nb.getHeight()) {
-            return null;
-        }
-
-        final double w = pb.width - nb.getWidth();
-        final double h = pb.height - nb.getHeight();
-
-        final int x2 = pb.x + (int) (w/2.0);
-        final int y2 = pb.y + (int) (h/2.0);
-
-        final int nbw = (int) nb.getWidth();
-        final int nbh = (int) nb.getHeight();
-
-        Rectangle centeredNBounds = new Rectangle(x2, y2, nbw, nbh);
-
-        // slower check to see if label is displayed inside primitive shape
-        if (area.contains(centeredNBounds)) {
-            return centeredNBounds;
-        }
-
-        // if center position (C) is not inside osm shape, try naively some other positions as follows:
-        // CHECKSTYLE.OFF: SingleSpaceSeparator
-        final int x1 = pb.x + (int)   (w/4.0);
-        final int x3 = pb.x + (int) (3*w/4.0);
-        final int y1 = pb.y + (int)   (h/4.0);
-        final int y3 = pb.y + (int) (3*h/4.0);
-        // CHECKSTYLE.ON: SingleSpaceSeparator
-        // +-----------+
-        // |  5  1  6  |
-        // |  4  C  2  |
-        // |  8  3  7  |
-        // +-----------+
-        Rectangle[] candidates = new Rectangle[] {
-                new Rectangle(x2, y1, nbw, nbh),
-                new Rectangle(x3, y2, nbw, nbh),
-                new Rectangle(x2, y3, nbw, nbh),
-                new Rectangle(x1, y2, nbw, nbh),
-                new Rectangle(x1, y1, nbw, nbh),
-                new Rectangle(x3, y1, nbw, nbh),
-                new Rectangle(x3, y3, nbw, nbh),
-                new Rectangle(x1, y3, nbw, nbh)
-        };
-        // Dumb algorithm to find a better placement. We could surely find a smarter one but it should
-        // solve most of building issues with only few calculations (8 at most)
-        for (int i = 0; i < candidates.length; i++) {
-            centeredNBounds = candidates[i];
-            if (area.contains(centeredNBounds)) {
-                return centeredNBounds;
-            }
-        }
-
-        // none found
-        return null;
     }
 
@@ -1181,4 +1109,31 @@
 
     /**
+     * Draws a text for the given primitive
+     * @param osm The primitive to draw the text for
+     * @param text The text definition (font/position/.../text content) to draw.
+     * @since 11722
+     */
+    public void drawText(OsmPrimitive osm, TextLabel text) {
+        PositionForAreaStrategy position = text.getLabelPositionSteategy();
+        if (position.supportsGlyphVector()) {
+            if (osm instanceof Way) {
+                // we might allow this for the outline of relations as well.
+                drawTextOnPath((Way) osm, text);
+            }
+        } else {
+            if (osm instanceof Way) {
+                drawAreaText(osm, text, getPath((Way) osm));
+            } else if (osm instanceof Relation) {
+                Multipolygon multipolygon = MultipolygonCache.getInstance().get(nc, (Relation) osm);
+                if (!multipolygon.getOuterWays().isEmpty()) {
+                    for (PolyData pd : multipolygon.getCombinedPolygons()) {
+                        drawAreaText(osm, text, pd.get());
+                    }
+                }
+            }
+        }
+    }
+
+    /**
      * Draws a text along a given way.
      * @param way The way to draw the text on.
@@ -1822,4 +1777,6 @@
                 if (drawMultipolygon && drawArea && s instanceof AreaElement && (flags & FLAG_DISABLED) == 0) {
                     output.add(new StyleRecord(s, osm, flags));
+                } else if (drawMultipolygon && drawArea && s instanceof TextElement) {
+                    output.add(new StyleRecord(s, osm, flags));
                 } else if (drawRestriction && s instanceof NodeElement) {
                     output.add(new StyleRecord(s, osm, flags));
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 11721)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 11722)
@@ -26,8 +26,8 @@
 import org.openstreetmap.josm.gui.mappaint.styleelement.BoxTextElement;
 import org.openstreetmap.josm.gui.mappaint.styleelement.LineElement;
-import org.openstreetmap.josm.gui.mappaint.styleelement.LineTextElement;
 import org.openstreetmap.josm.gui.mappaint.styleelement.NodeElement;
 import org.openstreetmap.josm.gui.mappaint.styleelement.RepeatImageElement;
 import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement;
+import org.openstreetmap.josm.gui.mappaint.styleelement.TextElement;
 import org.openstreetmap.josm.gui.mappaint.styleelement.TextLabel;
 import org.openstreetmap.josm.gui.util.GuiHelper;
@@ -366,5 +366,6 @@
             env.layer = e.getKey();
             if (osm instanceof Way) {
-                addIfNotNull(sl, AreaElement.create(env));
+                AreaElement areaStyle = AreaElement.create(env);
+                addIfNotNull(sl, areaStyle);
                 addIfNotNull(sl, RepeatImageElement.create(env));
                 addIfNotNull(sl, LineElement.createLine(env));
@@ -372,5 +373,9 @@
                 addIfNotNull(sl, LineElement.createRightCasing(env));
                 addIfNotNull(sl, LineElement.createCasing(env));
-                addIfNotNull(sl, LineTextElement.create(env));
+                addIfNotNull(sl, TextElement.create(env));
+                if (areaStyle != null) {
+                    //TODO: Warn about this, or even remove it completely
+                    addIfNotNull(sl, TextElement.createForContent(env));
+                }
             } else if (osm instanceof Node) {
                 NodeElement nodeStyle = NodeElement.create(env);
@@ -383,9 +388,14 @@
             } else if (osm instanceof Relation) {
                 if (((Relation) osm).isMultipolygon()) {
-                    addIfNotNull(sl, AreaElement.create(env));
+                    AreaElement areaStyle = AreaElement.create(env);
+                    addIfNotNull(sl, areaStyle);
                     addIfNotNull(sl, RepeatImageElement.create(env));
                     addIfNotNull(sl, LineElement.createLine(env));
                     addIfNotNull(sl, LineElement.createCasing(env));
-                    addIfNotNull(sl, LineTextElement.create(env));
+                    addIfNotNull(sl, TextElement.create(env));
+                    if (areaStyle != null) {
+                        //TODO: Warn about this, or even remove it completely
+                        addIfNotNull(sl, TextElement.createForContent(env));
+                    }
                 } else if (osm.hasTag("type", "restriction")) {
                     addIfNotNull(sl, NodeElement.create(env));
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/AreaElement.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/AreaElement.java	(revision 11721)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/AreaElement.java	(revision 11722)
@@ -10,10 +10,8 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
-import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
 import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
 import org.openstreetmap.josm.data.preferences.IntegerProperty;
 import org.openstreetmap.josm.gui.mappaint.Cascade;
 import org.openstreetmap.josm.gui.mappaint.Environment;
-import org.openstreetmap.josm.gui.mappaint.Keyword;
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
 import org.openstreetmap.josm.gui.util.RotationAngle;
@@ -120,13 +118,9 @@
         }
 
-        TextLabel text = null;
-        Keyword textPos = c.get(TEXT_POSITION, null, Keyword.class);
-        if (textPos == null || "center".equals(textPos.val)) {
-            text = TextLabel.create(env, PaintColors.AREA_TEXT.get(), true);
-        }
+        TextLabel text = null; // <- text is handled by TextElement
         MapImage iconImage = NodeElement.createIcon(env);
         RotationAngle rotationAngle = NodeElement.createRotationAngle(env);
 
-        if (iconImage != null || text != null) {
+        if (iconImage != null) {
             // fake a transparent color.
             color = new Color(0, 0, 0, 0);
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/LineTextElement.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/LineTextElement.java	(revision 11721)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/LineTextElement.java	(revision 11722)
@@ -13,4 +13,9 @@
 import org.openstreetmap.josm.gui.mappaint.Keyword;
 
+/**
+ * A text that is only on the line
+ * @deprecated since 11722. To be removed summer 2017
+ */
+@Deprecated
 public class LineTextElement extends StyleElement {
 
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/PositionForAreaStrategy.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/PositionForAreaStrategy.java	(revision 11722)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/PositionForAreaStrategy.java	(revision 11722)
@@ -0,0 +1,205 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.mappaint.styleelement;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.Rectangle2D;
+
+import org.openstreetmap.josm.gui.mappaint.Keyword;
+
+/**
+ * This strategy defines how to place a label or icon inside the area.
+ * @since 11720
+ */
+public interface PositionForAreaStrategy {
+    /**
+     * Finds the correct position of a label / icon inside the area.
+     * @param area The area to search in
+     * @param nb The bounding box of the thing we are searching a place for.
+     * @return The position as rectangle with the same dimension as nb. <code>null</code> if none was found.
+     */
+    Rectangle2D findLabelPlacement(Shape area, Rectangle2D nb);
+
+    /**
+     * Checks whether this placement strategy supports more detailed (rotation / ...) placement using a glyph vecotr.
+     * @return <code>true</code> if it is supported.
+     */
+    boolean supportsGlyphVector();
+
+    /**
+     * Gets a strategy for the given keyword.
+     * @param keyword The text position keyword.
+     * @return The strategy or line if none was specified.
+     * @since 11720
+     */
+    public static PositionForAreaStrategy forKeyword(Keyword keyword) {
+        return forKeyword(keyword, LINE);
+    }
+
+    /**
+     * Gets a strategy for the given keyword.
+     * @param keyword The text position keyword.
+     * @param defaultStrategy The default if no strategy was recognized.
+     * @return The strategy or line if none was specified.
+     * @since 11720
+     */
+    public static PositionForAreaStrategy forKeyword(Keyword keyword, PositionForAreaStrategy defaultStrategy) {
+        if (keyword == null) {
+            return defaultStrategy;
+        }
+        switch (keyword.val) {
+        case "center":
+            return PARTIALY_INSIDE;
+        case "inside":
+            return INSIDE;
+        case "line":
+            return LINE;
+        default:
+            return defaultStrategy;
+        }
+    }
+
+    /**
+     * Places the label onto the line.
+     *
+     * @since 11720
+     */
+    public static PositionForAreaStrategy LINE = new OnLineStrategy();
+
+    /**
+     * Places the label / icon so that it is completely inside the area.
+     *
+     * @since 11720
+     */
+    public static PositionForAreaStrategy INSIDE = new CompletelyInsideAreaStrategy();
+
+    /**
+     * Places the label / icon so that is is on the area.
+     * @since 11720
+     */
+    public static PositionForAreaStrategy PARTIALY_INSIDE = new PartialyInsideAreaStrategy();
+
+    /**
+     * Places the label onto the line.
+     *
+     * @since 11720
+     */
+    class OnLineStrategy implements PositionForAreaStrategy {
+        @Override
+        public Rectangle2D findLabelPlacement(Shape area, Rectangle2D nb) {
+            // cannot place inside area.
+            return null;
+        }
+
+        @Override
+        public boolean supportsGlyphVector() {
+            return true;
+        }
+    };
+
+    /**
+     * Places the label / icon so that it is completely inside the area.
+     *
+     * @since 11720
+     */
+    class CompletelyInsideAreaStrategy implements PositionForAreaStrategy {
+
+        @Override
+        public Rectangle2D findLabelPlacement(Shape area, Rectangle2D nb) {
+            // Using the Centroid is Nicer for buildings like: +--------+
+            // but this needs to be fast.  As most houses are  |   42   |
+            // boxes anyway, the center of the bounding box    +---++---+
+            // will have to do.                                    ++
+            // Centroids are not optimal either, just imagine a U-shaped house.
+
+            Rectangle pb = area.getBounds();
+
+            // quick check to see if label box is smaller than primitive box
+            if (pb.width < nb.getWidth() || pb.height < nb.getHeight()) {
+                return null;
+            }
+
+            final double w = pb.width - nb.getWidth();
+            final double h = pb.height - nb.getHeight();
+
+            final int x2 = pb.x + (int) (w / 2.0);
+            final int y2 = pb.y + (int) (h / 2.0);
+
+            final int nbw = (int) nb.getWidth();
+            final int nbh = (int) nb.getHeight();
+
+            Rectangle centeredNBounds = new Rectangle(x2, y2, nbw, nbh);
+
+            // slower check to see if label is displayed inside primitive shape
+            if (area.contains(centeredNBounds)) {
+                return centeredNBounds;
+            }
+
+            // if center position (C) is not inside osm shape, try naively some other positions as follows:
+            // CHECKSTYLE.OFF: SingleSpaceSeparator
+            final int x1 = pb.x + (int) (w / 4.0);
+            final int x3 = pb.x + (int) (3 * w / 4.0);
+            final int y1 = pb.y + (int) (h / 4.0);
+            final int y3 = pb.y + (int) (3 * h / 4.0);
+            // CHECKSTYLE.ON: SingleSpaceSeparator
+            // +-----------+
+            // |  5  1  6  |
+            // |  4  C  2  |
+            // |  8  3  7  |
+            // +-----------+
+            Rectangle[] candidates = new Rectangle[] { new Rectangle(x2, y1, nbw, nbh), new Rectangle(x3, y2, nbw, nbh),
+                    new Rectangle(x2, y3, nbw, nbh), new Rectangle(x1, y2, nbw, nbh), new Rectangle(x1, y1, nbw, nbh),
+                    new Rectangle(x3, y1, nbw, nbh), new Rectangle(x3, y3, nbw, nbh), new Rectangle(x1, y3, nbw, nbh) };
+            // Dumb algorithm to find a better placement. We could surely find a smarter one but it should
+            // solve most of building issues with only few calculations (8 at most)
+            for (int i = 0; i < candidates.length; i++) {
+                centeredNBounds = candidates[i];
+                if (area.contains(centeredNBounds)) {
+                    return centeredNBounds;
+                }
+            }
+
+            // none found
+            return null;
+        }
+
+        @Override
+        public boolean supportsGlyphVector() {
+            return false;
+        }
+    }
+
+    /**
+     * A strategy that places the label / icon so that is is on the area.
+     *
+     * The center of that place should be in the area, but the icon / label may overlap on the edges.
+     * @since 11720
+     */
+    public class PartialyInsideAreaStrategy extends CompletelyInsideAreaStrategy {
+        @Override
+        public Rectangle2D findLabelPlacement(Shape area, Rectangle2D nb) {
+            Rectangle2D inside = super.findLabelPlacement(area, nb);
+            if (inside != null) {
+                return inside;
+            }
+
+            double nbdx = Math.max(0, (nb.getWidth() - 20) / 2);
+            double nbdy = Math.max(0, (nb.getHeight() - 10) / 2);
+
+            if (nbdx < .5 && nbdy < .5) {
+                // we can't do any better
+                return null;
+            } else {
+                Rectangle2D smallNb = new Rectangle2D.Double(nb.getX() + nbdx, nb.getY() + nbdy,
+                        nb.getWidth() - 2 * nbdx, nb.getHeight() - 2 * nbdy);
+                Rectangle2D position = super.findLabelPlacement(area, smallNb);
+                if (position == null) {
+                    return null;
+                }
+                return new Rectangle2D.Double(position.getX() - nbdx, position.getY() - nbdy, nb.getWidth(),
+                        nb.getHeight());
+            }
+        }
+    }
+
+}
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/TextElement.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/TextElement.java	(revision 11722)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/TextElement.java	(revision 11722)
@@ -0,0 +1,87 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.mappaint.styleelement;
+
+import java.util.Objects;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
+import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
+import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
+import org.openstreetmap.josm.gui.mappaint.Cascade;
+import org.openstreetmap.josm.gui.mappaint.Environment;
+import org.openstreetmap.josm.gui.mappaint.Keyword;
+
+/**
+ * The text that is drawn for a way/area. It may be drawn along the outline or onto the way.
+ *
+ * @since 11720
+ */
+public class TextElement extends StyleElement {
+
+    private final TextLabel text;
+
+    protected TextElement(Cascade c, TextLabel text) {
+        super(c, 4.9f);
+        this.text = text;
+    }
+
+    /**
+     * Create a new text element
+     * @param env The environment to read the text data from
+     * @return The text element or <code>null</code> if it could not be created.
+     */
+    public static TextElement create(final Environment env) {
+        final Cascade c = env.mc.getCascade(env.layer);
+
+        TextLabel text = TextLabel.create(env, PaintColors.TEXT.get(), false);
+        if (text == null)
+            return null;
+        return new TextElement(c, text);
+    }
+
+    /**
+     * JOSM traditionally adds both line and content text elements if a fill style was set.
+     *
+     * For now, we simulate this by generating a TextElement if no text-position was provided.
+     * @param env The environment to read the text data from
+     * @return The text element or <code>null</code> if it could not be created.
+     */
+    public static TextElement createForContent(Environment env) {
+        final Cascade c = env.mc.getCascade(env.layer);
+        Keyword positionKeyword = c.get(AreaElement.TEXT_POSITION, null, Keyword.class);
+        if (positionKeyword != null) {
+            return null; // No need for this hack.
+        }
+
+        TextLabel text = TextLabel.create(env, PaintColors.TEXT.get(), true);
+        if (text == null) {
+            return null;
+        }
+        return new TextElement(c, text.withPosition(PositionForAreaStrategy.INSIDE));
+    }
+
+    @Override
+    public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, StyledMapRenderer painter,
+            boolean selected, boolean outermember, boolean member) {
+        painter.drawText(primitive, text);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null || getClass() != obj.getClass()) return false;
+        if (!super.equals(obj)) return false;
+        TextElement that = (TextElement) obj;
+        return Objects.equals(text, that.text);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(super.hashCode(), text);
+    }
+
+    @Override
+    public String toString() {
+        return "TextElement{" + super.toString() + "text=" + text + '}';
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/TextLabel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/TextLabel.java	(revision 11721)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/TextLabel.java	(revision 11722)
@@ -15,4 +15,5 @@
 import org.openstreetmap.josm.gui.mappaint.styleelement.LabelCompositionStrategy.StaticLabelCompositionStrategy;
 import org.openstreetmap.josm.gui.mappaint.styleelement.LabelCompositionStrategy.TagLookupCompositionStrategy;
+import org.openstreetmap.josm.gui.mappaint.styleelement.PositionForAreaStrategy.CompletelyInsideAreaStrategy;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.Utils;
@@ -54,4 +55,9 @@
      */
     public Color haloColor;
+
+    /**
+     * The position strategy for this text label.
+     */
+    private final PositionForAreaStrategy labelPositionSteategy;
 
     /**
@@ -66,15 +72,33 @@
      * @param haloRadius halo radius
      * @param haloColor halo color
-     */
+     * @deprecated since 11722, To be removed in mid-2017
+     */
+    @Deprecated
     public TextLabel(LabelCompositionStrategy strategy, Font font, int xOffset, int yOffset, Color color, Float haloRadius, Color haloColor) {
-        CheckParameterUtil.ensureParameterNotNull(font);
-        CheckParameterUtil.ensureParameterNotNull(color);
-        labelCompositionStrategy = strategy;
-        this.font = font;
+        this(strategy, font, xOffset, yOffset, color, haloRadius, haloColor, new CompletelyInsideAreaStrategy());
+    }
+
+    /**
+     * Creates a new text element
+     *
+     * @param strategy the strategy indicating how the text is composed for a specific {@link OsmPrimitive} to be rendered.
+     * If null, no label is rendered.
+     * @param font the font to be used. Must not be null.
+     * @param xOffset x offset
+     * @param yOffset y offset
+     * @param color the color to be used. Must not be null
+     * @param haloRadius halo radius
+     * @param haloColor halo color
+     * @param labelPositionSteategy The position in the area.
+     */
+    protected TextLabel(LabelCompositionStrategy strategy, Font font, int xOffset, int yOffset, Color color, Float haloRadius, Color haloColor, PositionForAreaStrategy labelPositionSteategy) {
+        this.labelCompositionStrategy = strategy;
+        this.font = Objects.requireNonNull(font, "font");
         this.xOffset = xOffset;
         this.yOffset = yOffset;
-        this.color = color;
+        this.color = Objects.requireNonNull(color, "color");
         this.haloRadius = haloRadius;
         this.haloColor = haloColor;
+        this.labelPositionSteategy = Objects.requireNonNull(labelPositionSteategy, "labelPositionSteategy");
     }
 
@@ -92,4 +116,22 @@
         this.haloColor = other.haloColor;
         this.haloRadius = other.haloRadius;
+        this.labelPositionSteategy = other.labelPositionSteategy;
+    }
+
+    /**
+     * Copy constructor that changes the position strategy.
+     *
+     * @param other the other element.
+     * @param labelPositionSteategy the position
+     */
+    private TextLabel(TextLabel other, PositionForAreaStrategy labelPositionSteategy) {
+        this.labelCompositionStrategy = other.labelCompositionStrategy;
+        this.font = other.font;
+        this.xOffset = other.xOffset;
+        this.yOffset = other.yOffset;
+        this.color = other.color;
+        this.haloColor = other.haloColor;
+        this.haloRadius = other.haloRadius;
+        this.labelPositionSteategy = labelPositionSteategy;
     }
 
@@ -177,5 +219,8 @@
         }
 
-        return new TextLabel(strategy, font, (int) xOffset, -(int) yOffset, color, haloRadius, haloColor);
+        Keyword positionKeyword = c.get(AreaElement.TEXT_POSITION, null, Keyword.class);
+        PositionForAreaStrategy position = PositionForAreaStrategy.forKeyword(positionKeyword);
+
+        return new TextLabel(strategy, font, (int) xOffset, -(int) yOffset, color, haloRadius, haloColor, position);
     }
 
@@ -190,4 +235,17 @@
         if (labelCompositionStrategy == null) return null;
         return labelCompositionStrategy.compose(osm);
+    }
+
+    /**
+     * Gets the strategy that defines where to place the label.
+     * @return The strategy. Never null.
+     * @since 11722
+     */
+    public PositionForAreaStrategy getLabelPositionSteategy() {
+        return labelPositionSteategy;
+    }
+
+    public TextLabel withPosition(PositionForAreaStrategy labelPositionSteategy) {
+        return new TextLabel(this, labelPositionSteategy);
     }
 
