Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 11729)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 11730)
@@ -39,4 +39,5 @@
 import java.util.concurrent.RecursiveTask;
 import java.util.function.BiConsumer;
+import java.util.function.Consumer;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
@@ -740,28 +741,24 @@
 
     /**
-     * Draw the icon for a given area. The icon is drawn around the lat/lon center of the area.
-     * @param primitive The node
-     * @param img The icon to draw at the node position
+     * Draw the icon for a given area. Normally, the icon is drawn around the center of the area.
+     * @param osm The primitive to draw the icon for
+     * @param img The icon to draw
      * @param disabled {@code} true to render disabled version, {@code false} for the standard version
      * @param selected {@code} true to render it as selected, {@code false} otherwise
      * @param member {@code} true to render it as a relation member, {@code false} otherwise
      * @param theta the angle of rotation in radians
+     * @param iconPosition Where to place the icon.
      * @since 11670
      */
-    public void drawAreaIcon(OsmPrimitive primitive, MapImage img, boolean disabled, boolean selected, boolean member, double theta) {
-        BBox bbox = null;
-        if (primitive instanceof Way) {
-            bbox = primitive.getBBox();
-        } else if (primitive instanceof Relation) {
-            Multipolygon multipolygon = MultipolygonCache.getInstance().get(nc, (Relation) primitive);
-            if (multipolygon != null) {
-                BBox collect = new BBox();
-                multipolygon.getOuterPolygons().forEach(p -> p.getNodes().forEach(n -> collect.add(n.getCoor())));
-                bbox = collect;
-            }
-        }
-
-        if (bbox != null && bbox.isValid()) {
-            MapViewPoint p = mapState.getPointFor(bbox.getCenter());
+    public void drawAreaIcon(OsmPrimitive osm, MapImage img, boolean disabled, boolean selected, boolean member, double theta, PositionForAreaStrategy iconPosition) {
+        Rectangle2D.Double iconRect = new Rectangle2D.Double(-img.getWidth() / 2.0, -img.getHeight() / 2.0, img.getWidth(), img.getHeight());
+
+        forEachPolygon(osm, path -> {
+            Shape area = path.createTransformedShape(mapState.getAffineTransform());
+            Rectangle2D placement = iconPosition.findLabelPlacement(area, iconRect);
+            if (placement == null) {
+                return;
+            }
+            MapViewPoint p = mapState.getForView(placement.getCenterX(), placement.getCenterY());
             drawIcon(p, img, disabled, selected, member, theta, (g, r) -> {
                 if (useStrokes) {
@@ -774,5 +771,5 @@
                 g.draw(r);
             });
-        }
+        });
     }
 
@@ -1122,12 +1119,21 @@
             }
         } 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());
-                    }
+            forEachPolygon(osm, path -> drawAreaText(osm, text, path));
+        }
+    }
+
+    /**
+     * Calls a consumer for each path of the area shape-
+     * @param osm A way or a multipolygon
+     * @param consumer The consumer to call.
+     */
+    private void forEachPolygon(OsmPrimitive osm, Consumer<Path2D.Double> consumer) {
+        if (osm instanceof Way) {
+            consumer.accept(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()) {
+                    consumer.accept(pd.get());
                 }
             }
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 11729)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 11730)
@@ -24,4 +24,5 @@
 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
 import org.openstreetmap.josm.gui.mappaint.styleelement.AreaElement;
+import org.openstreetmap.josm.gui.mappaint.styleelement.AreaIconElement;
 import org.openstreetmap.josm.gui.mappaint.styleelement.BoxTextElement;
 import org.openstreetmap.josm.gui.mappaint.styleelement.LineElement;
@@ -373,4 +374,5 @@
                 addIfNotNull(sl, LineElement.createRightCasing(env));
                 addIfNotNull(sl, LineElement.createCasing(env));
+                addIfNotNull(sl, AreaIconElement.create(env));
                 addIfNotNull(sl, TextElement.create(env));
                 if (areaStyle != null) {
@@ -393,4 +395,5 @@
                     addIfNotNull(sl, LineElement.createLine(env));
                     addIfNotNull(sl, LineElement.createCasing(env));
+                    addIfNotNull(sl, AreaIconElement.create(env));
                     addIfNotNull(sl, TextElement.create(env));
                     if (areaStyle != null) {
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/AreaElement.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/AreaElement.java	(revision 11729)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/AreaElement.java	(revision 11730)
@@ -15,5 +15,4 @@
 import org.openstreetmap.josm.gui.mappaint.Environment;
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
-import org.openstreetmap.josm.gui.util.RotationAngle;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.Utils;
@@ -44,6 +43,8 @@
     /**
      * The text that should be written on this area.
+     * @deprecated Use {@link TextElement} instead.
      */
-    public TextLabel text;
+    @Deprecated
+    public TextLabel text = null;
 
     /**
@@ -63,16 +64,5 @@
     public Float extentThreshold;
 
-    /**
-     * The icon that is displayed on the center of the area.
-     */
-    private final MapImage iconImage;
-
-    /**
-     * The rotation of the {@link #iconImageAngle}
-     */
-    private final RotationAngle iconImageAngle;
-
-    protected AreaElement(Cascade c, Color color, MapImage fillImage, Float extent,
-            Float extentThreshold, TextLabel text, MapImage iconImage, RotationAngle iconImageAngle) {
+    protected AreaElement(Cascade c, Color color, MapImage fillImage, Float extent, Float extentThreshold) {
         super(c, 1f);
         CheckParameterUtil.ensureParameterNotNull(color);
@@ -81,7 +71,4 @@
         this.extent = extent;
         this.extentThreshold = extentThreshold;
-        this.text = text;
-        this.iconImage = iconImage;
-        this.iconImageAngle = iconImageAngle;
     }
 
@@ -118,18 +105,9 @@
         }
 
-        TextLabel text = null; // <- text is handled by TextElement
-        MapImage iconImage = NodeElement.createIcon(env);
-        RotationAngle rotationAngle = NodeElement.createRotationAngle(env);
-
-        if (iconImage != null) {
-            // fake a transparent color.
-            color = new Color(0, 0, 0, 0);
-        }
-
         if (color != null) {
             Float extent = c.get(FILL_EXTENT, null, float.class);
             Float extentThreshold = c.get(FILL_EXTENT_THRESHOLD, null, float.class);
 
-            return new AreaElement(c, color, fillImage, extent, extentThreshold, text, iconImage, rotationAngle);
+            return new AreaElement(c, color, fillImage, extent, extentThreshold);
         } else {
             return null;
@@ -156,9 +134,4 @@
             painter.drawArea((Relation) osm, myColor, fillImage, extent, extentThreshold, painter.isInactiveMode() || osm.isDisabled(), text);
         }
-
-        if (iconImage != null && painter.isShowIcons()) {
-            painter.drawAreaIcon(osm, iconImage, painter.isInactiveMode() || osm.isDisabled(), selected, member,
-                    iconImageAngle == null ? 0.0 : iconImageAngle.getRotationAngle(osm));
-        }
     }
 
@@ -171,14 +144,11 @@
         return Objects.equals(color, that.color) &&
                 Objects.equals(fillImage, that.fillImage) &&
-                Objects.equals(text, that.text) &&
                 Objects.equals(extent, that.extent) &&
-                Objects.equals(extentThreshold, that.extentThreshold) &&
-                Objects.equals(iconImage, that.iconImage) &&
-                Objects.equals(iconImageAngle, that.iconImageAngle);
+                Objects.equals(extentThreshold, that.extentThreshold);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(super.hashCode(), color, fillImage, text, extent, extentThreshold, iconImage, iconImageAngle);
+        return Objects.hash(super.hashCode(), color, fillImage, extent, extentThreshold);
     }
 
@@ -186,5 +156,5 @@
     public String toString() {
         return "AreaElemStyle{" + super.toString() + "color=" + Utils.toString(color) +
-                " fillImage=[" + fillImage + "] iconImage=[" + iconImage + "] iconImageAngle=[" + iconImageAngle + "]}";
+                " fillImage=[" + fillImage + "] extent=[" + extent + "] extentThreshold=[" + extentThreshold + "]}";
     }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/AreaIconElement.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/AreaIconElement.java	(revision 11730)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/AreaIconElement.java	(revision 11730)
@@ -0,0 +1,97 @@
+// 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.StyledMapRenderer;
+import org.openstreetmap.josm.gui.mappaint.Cascade;
+import org.openstreetmap.josm.gui.mappaint.Environment;
+import org.openstreetmap.josm.gui.util.RotationAngle;
+
+/**
+ * This class defines how an icon is rendered onto the area.
+ * @author Michael Zangl
+ * @since 11729
+ */
+public class AreaIconElement extends StyleElement {
+    /**
+     * The icon that is displayed on the center of the area.
+     */
+    private final MapImage iconImage;
+
+    /**
+     * The rotation of the {@link #iconImageAngle}
+     */
+    private final RotationAngle iconImageAngle;
+
+    /**
+     * The position of the icon inside the area.
+     */
+    private final PositionForAreaStrategy iconPosition = PositionForAreaStrategy.PARTIALY_INSIDE;
+
+    private AreaIconElement(Cascade c, MapImage iconImage, RotationAngle iconImageAngle) {
+        super(c, 4.8f);
+        this.iconImage = Objects.requireNonNull(iconImage, "iconImage");
+        this.iconImageAngle = Objects.requireNonNull(iconImageAngle, "iconImageAngle");
+    }
+
+    @Override
+    public void paintPrimitive(OsmPrimitive osm, MapPaintSettings paintSettings, StyledMapRenderer painter,
+            boolean selected, boolean outermember, boolean member) {
+        if (painter.isShowIcons()) {
+            painter.drawAreaIcon(osm, iconImage, painter.isInactiveMode() || osm.isDisabled(), selected, member,
+                    iconImageAngle.getRotationAngle(osm), iconPosition);
+        }
+    }
+
+    /**
+     * Create a new {@link AreaIconElement}
+     * @param env The current style definitions
+     * @return The area element or <code>null</code> if there is no icon.
+     */
+    public static AreaIconElement create(final Environment env) {
+        final Cascade c = env.mc.getCascade(env.layer);
+        MapImage iconImage = NodeElement.createIcon(env);
+        if (iconImage != null) {
+            RotationAngle rotationAngle = NodeElement.createRotationAngle(env);
+
+            return new AreaIconElement(c, iconImage, rotationAngle);
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + ((iconImage == null) ? 0 : iconImage.hashCode());
+        result = prime * result + ((iconImageAngle == null) ? 0 : iconImageAngle.hashCode());
+        result = prime * result + ((iconPosition == null) ? 0 : iconPosition.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!super.equals(obj)) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        AreaIconElement other = (AreaIconElement) obj;
+        return Objects.equals(iconImage, other.iconImage) &&
+                Objects.equals(iconImageAngle, other.iconImageAngle) &&
+                Objects.equals(iconPosition, other.iconPosition);
+    }
+
+    @Override
+    public String toString() {
+        return "AreaIconElement{" + super.toString() + "iconImage=[" + iconImage + "] iconImageAngle=[" + iconImageAngle + "]}";
+    }
+}
