Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 8993)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 8994)
@@ -26,5 +26,4 @@
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
-import java.text.Bidi;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -1248,35 +1247,29 @@
         }
 
-        FontRenderContext frc = g.getFontRenderContext();
-        char[] chars = name.toCharArray();
-        int dirFlag = Bidi.DIRECTION_LEFT_TO_RIGHT;
-        if (Bidi.requiresBidi(chars, 0, chars.length)) {
-            Bidi bd = new Bidi(name, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
-            if (bd.isRightToLeft()) {
-                dirFlag = Bidi.DIRECTION_RIGHT_TO_LEFT;
-            }
-        }
-        // only works for text that is completely left-to-right or completely right-to-left, not bi-directional text
-        GlyphVector gv = text.font.layoutGlyphVector(frc, chars, 0, chars.length, dirFlag);
-
-        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);
-            if (p != null) {
-                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);
-                if (isGlyphVectorDoubleTranslationBug(text.font)) {
-                    // scale the translation components by one half
-                    AffineTransform tmp = AffineTransform.getTranslateInstance(-0.5 * trfm.getTranslateX(), -0.5 * trfm.getTranslateY());
-                    tmp.concatenate(trfm);
-                    trfm = tmp;
-                }
-                gv.setGlyphTransform(i, trfm);
-            }
-        }
-        displayText(gv, null, 0, 0, way.isDisabled(), text);
+        List<GlyphVector> gvs = Utils.getGlyphVectorsBidi(name, text.font, g.getFontRenderContext());
+        double gvOffset = 0;
+        for (GlyphVector gv : gvs) {
+            double gvWidth = gv.getLogicalBounds().getBounds2D().getWidth();
+            for (int i = 0; i < gv.getNumGlyphs(); ++i) {
+                Rectangle2D rect = gv.getGlyphLogicalBounds(i).getBounds2D();
+                double t = tStart + offsetSign * (gvOffset + rect.getX() + rect.getWidth()/2) / pathLength;
+                double[] p = pointAt(t, poly, pathLength);
+                if (p != null) {
+                    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);
+                    if (isGlyphVectorDoubleTranslationBug(text.font)) {
+                        // scale the translation components by one half
+                        AffineTransform tmp = AffineTransform.getTranslateInstance(-0.5 * trfm.getTranslateX(), -0.5 * trfm.getTranslateY());
+                        tmp.concatenate(trfm);
+                        trfm = tmp;
+                    }
+                    gv.setGlyphTransform(i, trfm);
+                }
+            }
+            displayText(gv, null, 0, 0, way.isDisabled(), text);
+            gvOffset += gvWidth;
+        }
     }
 
Index: /trunk/src/org/openstreetmap/josm/tools/Utils.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 8993)
+++ /trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 8994)
@@ -6,4 +6,5 @@
 
 import java.awt.Color;
+import java.awt.Font;
 import java.awt.Toolkit;
 import java.awt.datatransfer.Clipboard;
@@ -13,4 +14,6 @@
 import java.awt.datatransfer.Transferable;
 import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
 import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
@@ -34,4 +37,5 @@
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.text.Bidi;
 import java.text.MessageFormat;
 import java.util.AbstractCollection;
@@ -1493,3 +1497,48 @@
         return hashMapInitialCapacity(nEntries, 0.75f);
     }
+
+    /**
+     * Utility class to save a string along with its rendering direction
+     * (left-to-right or right-to-left).
+     */
+    private static class DirectionString {
+        public int direction;
+        public String str;
+
+        public DirectionString(int direction, String str) {
+            this.direction = direction;
+            this.str = str;
+        }
+    }
+
+    /**
+     * Convert a string to a list of {@link GlyphVector}s. The string may contain
+     * bi-directional text. The result will be in correct visual order.
+     * Each element of the resulting list corresponds to one section of the
+     * string with consistent writing direction (left-to-right or right-to-left).
+     *
+     * @param string the string to render
+     * @param font the font
+     * @param frc a FontRenderContext object
+     * @return a list of GlyphVectors
+     */
+    public static List<GlyphVector> getGlyphVectorsBidi(String string, Font font, FontRenderContext frc) {
+        List<GlyphVector> gvs = new ArrayList<>();
+        Bidi bidi = new Bidi(string, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
+        byte[] levels = new byte[bidi.getRunCount()];
+        DirectionString[] dirStrings = new DirectionString[levels.length];
+        for (int i = 0; i < levels.length; ++i) {
+            levels[i] = (byte) bidi.getRunLevel(i);
+            String substr = string.substring(bidi.getRunStart(i), bidi.getRunLimit(i));
+            int dir = levels[i] % 2 == 0 ? Bidi.DIRECTION_LEFT_TO_RIGHT : Bidi.DIRECTION_RIGHT_TO_LEFT;
+            dirStrings[i] = new DirectionString(dir, substr);
+        }
+        Bidi.reorderVisually(levels, 0, dirStrings, 0, levels.length);
+        for (int i = 0; i < dirStrings.length; ++i) {
+            char[] chars = dirStrings[i].str.toCharArray();
+            gvs.add(font.layoutGlyphVector(frc, chars, 0, chars.length, dirStrings[i].direction));
+        }
+        return gvs;
+    }
+
 }
