Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 4005)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 4006)
@@ -116,5 +116,5 @@
      */
     public void drawWay(Way way, Color color, BasicStroke line, BasicStroke dashes, Color dashedColor,
-            TextElement text, boolean showOrientation, boolean showHeadArrowOnly,
+            boolean showOrientation, boolean showHeadArrowOnly,
             boolean showOneway, boolean onewayReversed) {
 
@@ -204,5 +204,4 @@
         }
         displaySegments(path, orientationArrows, onewayArrows, onewayArrowsCasing, color, line, dashes, dashedColor);
-        drawTextOnPath(way, text);
     }
 
@@ -247,5 +246,5 @@
     }
 
-    private void drawTextOnPath(Way way, TextElement text) {
+    public void drawTextOnPath(Way way, TextElement text) {
         if (text == null)
             return;
@@ -348,4 +347,49 @@
         }
         return null;
+    }
+
+    public void drawLinePattern(Way way, ImageIcon pattern) {
+        final int width = pattern.getIconWidth();
+        final int height = pattern.getIconHeight();
+
+        Point lastP = null;
+        double wayLength = 0;
+
+        Iterator<Node> it = way.getNodes().iterator();
+        while (it.hasNext()) {
+            Node n = it.next();
+            Point thisP = nc.getPoint(n);
+
+            if (lastP != null) {
+                final double segmentLength = thisP.distance(lastP);
+
+                final double dx = thisP.x - lastP.x;
+                final double dy = thisP.y - lastP.y;
+
+                double dist = wayLength == 0 ? 0 : width - (wayLength % width);
+
+                AffineTransform saveTransform = g.getTransform();
+                g.translate(lastP.x, lastP.y);
+                g.rotate(Math.atan2(dy, dx));
+
+                if (dist > 0) {
+                    g.drawImage(pattern.getImage(), 0, 0, (int) dist, height,
+                            width - (int) dist, 0, width, height, null);
+                }
+                while (dist < segmentLength) {
+                    if (dist + width > segmentLength) {
+                        g.drawImage(pattern.getImage(), (int) dist, 0, (int) segmentLength, height,
+                                0, 0, (int) segmentLength - (int) dist, height, null);
+                    } else {
+                        pattern.paintIcon(nc, g, (int) dist, 0);
+                    }
+                    dist += width;
+                }
+                g.setTransform(saveTransform);
+
+                wayLength += segmentLength;
+            }
+            lastP = thisP;
+        }
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java	(revision 4005)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java	(revision 4006)
@@ -34,4 +34,8 @@
 
     public abstract void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, MapPainter painter, boolean selected, boolean member);
+
+    public boolean isProperLineStyle() {
+        return false;
+    }
 
     /**
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 4005)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 4006)
@@ -64,12 +64,12 @@
             }
         } else if (osm instanceof Way) {
-            boolean hasNonModifierLine = false;
+            boolean hasProperLineStyle = false;
             for (ElemStyle s : p.a) {
-                if (s instanceof LineElemStyle && !s.isModifier) {
-                    hasNonModifierLine = true;
+                if (s.isProperLineStyle()) {
+                    hasProperLineStyle = true;
                     break;
                 }
             }
-            if (!hasNonModifierLine) {
+            if (!hasProperLineStyle) {
                 AreaElemStyle area = Utils.find(p.a, AreaElemStyle.class);
                 LineElemStyle line = (area == null ? LineElemStyle.UNTAGGED_WAY : LineElemStyle.createSimpleLineStyle(area.color));
@@ -92,5 +92,4 @@
 
             boolean isOuterWayOfSomeMP = false;
-            boolean hasIndependentLineElemStyle = false;
             Color wayColor = null;
 
@@ -104,4 +103,5 @@
 
                 if (multipolygon.getOuterWays().contains(osm)) {
+                    boolean hasIndependentLineStyle = false;
                     if (!isOuterWayOfSomeMP) { // do this only one time
                         List<ElemStyle> tmp = new ArrayList<ElemStyle>(p.a.size());
@@ -111,18 +111,26 @@
                             } else {
                                 tmp.add(s);
+                                if (s.isProperLineStyle()) {
+                                    hasIndependentLineStyle = true;
+                                }
                             }
                         }
                         p.a = new StyleList(tmp);
                         isOuterWayOfSomeMP = true;
-                        hasIndependentLineElemStyle = Utils.exists(p.a, LineElemStyle.class);
-                    }
-
-                    if (!hasIndependentLineElemStyle) {
+                    }
+
+                    if (!hasIndependentLineStyle) {
                         Pair<StyleList, Range> mpElemStyles = getStyleCacheWithRange(r, scale, nc);
-                        LineElemStyle mpLine = Utils.find(mpElemStyles.a, LineElemStyle.class);
+                        ElemStyle mpLine = null;
+                        for (ElemStyle s : mpElemStyles.a) {
+                            if (s.isProperLineStyle()) {
+                                mpLine = s;
+                                break;
+                            }
+                        }
                         if (mpLine != null) {
-                                p.a = new StyleList(p.a, mpLine);
-                                p.b = Range.cut(p.b, mpElemStyles.b);
-                                break;
+                            p.a = new StyleList(p.a, mpLine);
+                            p.b = Range.cut(p.b, mpElemStyles.b);
+                            break;
                         } else if (wayColor == null) {
                             AreaElemStyle mpArea = Utils.find(mpElemStyles.a, AreaElemStyle.class);
@@ -136,5 +144,12 @@
             }
             if (isOuterWayOfSomeMP) {
-                if (!Utils.exists(p.a, LineElemStyle.class)) {
+                boolean hasLineStyle = false;
+                for (ElemStyle s : p.a) {
+                    if (s.isProperLineStyle()) {
+                        hasLineStyle = true;
+                        break;
+                    }
+                }
+                if (!hasLineStyle) {
                     p.a = new StyleList(p.a, LineElemStyle.createSimpleLineStyle(wayColor));
                 }
@@ -155,5 +170,5 @@
                     boolean hasIndependentElemStyle = false;
                     for (ElemStyle s : p.a) {
-                        if (s instanceof LineElemStyle || s instanceof AreaElemStyle) {
+                        if (s.isProperLineStyle() || s instanceof AreaElemStyle) {
                             hasIndependentElemStyle = true;
                         }
@@ -226,6 +241,8 @@
             if (osm instanceof Way) {
                 addIfNotNull(sl, AreaElemStyle.create(c));
+                addIfNotNull(sl, LinePatternElemStyle.create(env));
                 addIfNotNull(sl, LineElemStyle.createLine(env));
                 addIfNotNull(sl, LineElemStyle.createCasing(env));
+                addIfNotNull(sl, LineTextElemStyle.create(env));
             } else if (osm instanceof Node) {
                 addIfNotNull(sl, NodeElemStyle.create(env));
@@ -233,6 +250,8 @@
                 if (((Relation)osm).isMultipolygon()) {
                     addIfNotNull(sl, AreaElemStyle.create(c));
+                    addIfNotNull(sl, LinePatternElemStyle.create(env));
                     addIfNotNull(sl, LineElemStyle.createLine(env));
                     addIfNotNull(sl, LineElemStyle.createCasing(env));
+                    addIfNotNull(sl, LineTextElemStyle.create(env));
                 } else if ("restriction".equals(osm.get("type"))) {
                     addIfNotNull(sl, NodeElemStyle.create(env));
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 4005)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 4006)
@@ -30,10 +30,9 @@
     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, TextElement text, float realWidth) {
+    protected LineElemStyle(Cascade c, BasicStroke line, Color color, BasicStroke dashesLine, Color dashesBackground, float realWidth) {
         super(c, 0f);
         this.line = line;
@@ -41,5 +40,4 @@
         this.dashesLine = dashesLine;
         this.dashesBackground = dashesBackground;
-        this.text = text;
         this.realWidth = realWidth;
     }
@@ -181,13 +179,5 @@
         }
 
-        TextElement text = null;
-        if (!casing) {
-            Keyword textPos = c.get("text-position", null, Keyword.class);
-            if (textPos == null || equal(textPos.val, "line")) {
-                text = TextElement.create(c, PaintColors.TEXT.get(), false);
-            }
-        }
-
-        return new LineElemStyle(c, line, color, dashesLine, dashesBackground, text, realWidth);
+        return new LineElemStyle(c, line, color, dashesLine, dashesBackground, realWidth);
     }
 
@@ -235,5 +225,5 @@
         }
 
-        painter.drawWay(w, myColor, myLine, myDashLine, myDashedColor, text, showOrientation,
+        painter.drawWay(w, myColor, myLine, myDashLine, myDashedColor, showOrientation,
                 showOnlyHeadArrowOnly, showOneway, onewayReversed);
 
@@ -252,4 +242,9 @@
 
     @Override
+    public boolean isProperLineStyle() {
+        return !isModifier;
+    }
+
+    @Override
     public boolean equals(Object obj) {
         if (obj == null || getClass() != obj.getClass())
@@ -259,9 +254,8 @@
         final LineElemStyle other = (LineElemStyle) obj;
         return  equal(line, other.line) &&
-        equal(color, other.color) &&
-        equal(dashesLine, other.dashesLine) &&
-        equal(dashesBackground, other.dashesBackground) &&
-        equal(text, other.text) &&
-        realWidth == other.realWidth;
+            equal(color, other.color) &&
+            equal(dashesLine, other.dashesLine) &&
+            equal(dashesBackground, other.dashesBackground) &&
+            realWidth == other.realWidth;
     }
 
@@ -273,5 +267,4 @@
         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;
@@ -281,8 +274,8 @@
     public String toString() {
         return "LineElemStyle{" + super.toString() + "width=" + line.getLineWidth() +
-        " realWidth=" + realWidth + " color=" + Utils.toString(color) +
-        " dashed=" + Arrays.toString(line.getDashArray()) +
-        (line.getDashPhase() == 0f ? "" : " dashesOffses=" + line.getDashPhase()) +
-        " dashedColor=" + Utils.toString(dashesBackground) + '}';
+            " realWidth=" + realWidth + " color=" + Utils.toString(color) +
+            " dashed=" + Arrays.toString(line.getDashArray()) +
+            (line.getDashPhase() == 0f ? "" : " dashesOffses=" + line.getDashPhase()) +
+            " dashedColor=" + Utils.toString(dashesBackground) + '}';
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/LinePatternElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/LinePatternElemStyle.java	(revision 4006)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/LinePatternElemStyle.java	(revision 4006)
@@ -0,0 +1,66 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.mappaint;
+
+import javax.swing.ImageIcon;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
+import org.openstreetmap.josm.data.osm.visitor.paint.MapPainter;
+import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
+
+/**
+ * similar to mapnik's LinePatternSymbolizer
+ */
+public class LinePatternElemStyle extends ElemStyle {
+
+    public ImageIcon pattern;
+
+    public LinePatternElemStyle(Cascade c, ImageIcon pattern) {
+        super(c, -1f);
+        this.pattern = pattern;
+    }
+
+    public static LinePatternElemStyle create(Environment env) {
+        Cascade c = env.mc.getCascade(env.layer);
+
+        IconReference iconRef = c.get("pattern-image", null, IconReference.class);
+        if (iconRef == null)
+            return null;
+        ImageIcon icon = MapPaintStyles.getIcon(iconRef, false);
+        if (icon == null)
+            return null;
+        return new LinePatternElemStyle(c, icon);
+    }
+
+    @Override
+    public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, MapPainter painter, boolean selected, boolean member) {
+        Way w = (Way)primitive;
+        painter.drawLinePattern(w, pattern);
+    }
+
+    @Override
+    public boolean isProperLineStyle() {
+        return true;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+        if (!super.equals(obj))
+            return false;
+        final LinePatternElemStyle other = (LinePatternElemStyle) obj;
+        return pattern.getImage() == other.pattern.getImage();
+    }
+
+    @Override
+    public int hashCode() {
+        return pattern.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "LinePatternElemStyle{" + super.toString() + "pattern=" + pattern + '}';
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/LineTextElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/LineTextElemStyle.java	(revision 4006)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/LineTextElemStyle.java	(revision 4006)
@@ -0,0 +1,50 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.mappaint;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Way;
+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.tools.Utils;
+
+public class LineTextElemStyle extends ElemStyle {
+    
+    private TextElement text;
+
+    protected LineTextElemStyle(Cascade c, TextElement text) {
+        super(c, 2f);
+        this.text = text;
+    }
+    public static LineTextElemStyle create(Environment env) {
+        Cascade c = env.mc.getCascade(env.layer);
+
+        Keyword textPos = c.get("text-position", null, Keyword.class);
+        if (textPos != null && !Utils.equal(textPos.val, "line"))
+            return null;
+
+        TextElement text = TextElement.create(c, PaintColors.TEXT.get(), false);
+        return new LineTextElemStyle(c, text);
+    }
+
+    @Override
+    public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, MapPainter painter, boolean selected, boolean member) {
+        Way w = (Way)primitive;
+        painter.drawTextOnPath(w, text);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+        if (!super.equals(obj))
+            return false;
+        final LineTextElemStyle other = (LineTextElemStyle) obj;
+        return Utils.equal(text, other.text);
+    }
+
+    @Override
+    public int hashCode() {
+        return text.hashCode();
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java	(revision 4005)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java	(revision 4006)
@@ -40,5 +40,5 @@
         public void execute(Environment env) {
             Object value = (val instanceof Expression) ? ((Expression) val).evaluate(env) : val;
-            if (key.equals("icon-image") || key.equals("fill-image")) {
+            if (key.equals("icon-image") || key.equals("fill-image") || key.equals("pattern-image")) {
                 if (value instanceof String) {
                     value = new IconReference((String) value, env.source);
