Index: resources/styles/builtin-tag-list
===================================================================
--- resources/styles/builtin-tag-list	(revision 2673)
+++ resources/styles/builtin-tag-list	(working copy)
@@ -13,7 +13,6 @@
 exit:to
 int_ref
 junction
-maxspeed
 name
 nat_ref
 oneway
Index: resources/styles/default/inc/roadspeed
===================================================================
--- resources/styles/default/inc/roadspeed	(revision 0)
+++ resources/styles/default/inc/roadspeed	(revision 0)
@@ -0,0 +1,25 @@
+#
+# Sets the road speed based on the maxspeed tag.
+# In case mkgmap:road-speed-class is set the element 
+# road_speed is overriden.
+#
+# road_speed classification:
+# road_speed | highest speed
+#  7         | No speed limit
+#  6         | 70 mph / 110 km/h
+#  5         | 60 mph /  90 km/h
+#  4         | 50 mph /  80 km/h
+#  3         | 35 mph /  60 km/h
+#  2         | 25 mph /  40 km/h
+#  1         | 15 mph /  20 km/h
+#  0         |  3 mph /   5 km/h
+#
+
+maxspeed=* &                              maxspeedkmh() > 110 { set mkgmap:road-speed-class = 7 }
+maxspeed=* & mkgmap:road-speed-class!=* & maxspeedkmh() >  90 { set mkgmap:road-speed-class = 6 }
+maxspeed=* & mkgmap:road-speed-class!=* & maxspeedkmh() >  80 { set mkgmap:road-speed-class = 5 }
+maxspeed=* & mkgmap:road-speed-class!=* & maxspeedkmh() >  60 { set mkgmap:road-speed-class = 4 }
+maxspeed=* & mkgmap:road-speed-class!=* & maxspeedkmh() >  40 { set mkgmap:road-speed-class = 3 }
+maxspeed=* & mkgmap:road-speed-class!=* & maxspeedkmh() >  20 { set mkgmap:road-speed-class = 2 }
+maxspeed=* & mkgmap:road-speed-class!=* & maxspeedkmh() >   5 { set mkgmap:road-speed-class = 1 }
+maxspeed=* & mkgmap:road-speed-class!=* & maxspeedkmh()=*     { set mkgmap:road-speed-class = 0 }
Index: resources/styles/default/lines
===================================================================
--- resources/styles/default/lines	(revision 2673)
+++ resources/styles/default/lines	(working copy)
@@ -110,6 +110,9 @@
 (man_made=pier | man_made=piste:halfpipe) & area!=yes
 {add highway=footway; name '${ref} ${name}' | '${ref}' | '${name}' }
 
+# calculate the road speed based on maxspeed tag
+include 'inc/roadspeed'; 
+
 # Roundabouts
 junction=roundabout & highway=trunk [0x0c road_class=3 road_speed=2 resolution 18]
 junction=roundabout & highway=primary [0x0c road_class=3 road_speed=2 resolution 19]
Index: src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(revision 2673)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(working copy)
@@ -128,9 +128,6 @@
 	private boolean driveOnLeft;
 	private boolean driveOnRight;
 	private final boolean checkRoundabouts;
-	private static final Pattern ENDS_IN_MPH_PATTERN = Pattern.compile(".*mph");
-	private static final Pattern REMOVE_MPH_PATTERN = Pattern.compile("[ \t]*mph");
-	private static final Pattern REMOVE_KPH_PATTERN = Pattern.compile("[ \t]*kmh");
 	private static final Pattern SEMI_PATTERN = Pattern.compile(";");
 
 	class AccessMapping {
@@ -1435,17 +1432,28 @@
 		}
 		road.setRoadClass(roadClass);
 
-		// road speed (can be overridden by maxspeed (OSM) tag or
+		// road speed (can be overridden by mkgmap:road-speed-class tag or
 		// mkgmap:road-speed tag)
 		int roadSpeed = gt.getRoadSpeed();
 		if(!ignoreMaxspeeds) {
-			// maxspeed attribute overrides default for road type
-			String maxSpeed = way.getTag("maxspeed");
-			if(maxSpeed != null) {
-				int rs = getSpeedIdx(maxSpeed);
-				if(rs >= 0)
-					roadSpeed = rs;
-				log.debug(debugWayName + " maxspeed=" + maxSpeed + ", speedIndex=" + roadSpeed);
+			String roadSpeedOverride = way.getTag("mkgmap:road-speed-class");
+			if (roadSpeedOverride != null) {
+				try {
+					int rs = Integer.decode(roadSpeedOverride);
+					if (rs >= 0 && rs <= 7) {
+						// override the road speed class
+						roadSpeed = rs;
+						log.error("Set road speed to "+rs+" "+way.getTag("maxspeed"));
+					} else {
+						log.error(debugWayName
+								+ " road classification mkgmap:road-speed-class="
+								+ roadSpeedOverride + " must be in [0;7]");
+					}
+				} catch (Exception exp) {
+					log.error(debugWayName
+							+ " road classification mkgmap:road-speed-class="
+							+ roadSpeedOverride + " must be in [0;7]");
+				}
 			}
 		}
 		val = way.getTag("mkgmap:road-speed");
@@ -1742,43 +1750,6 @@
 		}
 	}
 
-	private int getSpeedIdx(String tag) {
-		double factor = 1.0;
-		
-		String speedTag = tag.toLowerCase().trim();
-		
-		if (ENDS_IN_MPH_PATTERN.matcher(speedTag).matches()) {
-			// Check if it is a limit in mph
-			speedTag = REMOVE_MPH_PATTERN.matcher(speedTag).replaceFirst("");
-			factor = 1.61;
-		} else
-			speedTag = REMOVE_KPH_PATTERN.matcher(speedTag).replaceFirst("");  // get rid of kmh just in case
-
-		double kmh;
-		try {
-			kmh = Integer.parseInt(speedTag) * factor;
-		} catch (Exception e) {
-			return -1;
-		}
-		
-		if(kmh > 110)
-			return 7;
-		if(kmh > 90)
-			return 6;
-		if(kmh > 80)
-			return 5;
-		if(kmh > 60)
-			return 4;
-		if(kmh > 40)
-			return 3;
-		if(kmh > 20)
-			return 2;
-		if(kmh > 10)
-			return 1;
-		else
-			return 0;
-	}
-
 	protected boolean accessExplicitlyAllowed(String val) {
 		if (val == null)
 			return false;
Index: src/uk/me/parabola/mkgmap/osmstyle/function/MaxSpeedKmhFunction.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/function/MaxSpeedKmhFunction.java	(revision 0)
+++ src/uk/me/parabola/mkgmap/osmstyle/function/MaxSpeedKmhFunction.java	(revision 0)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+package uk.me.parabola.mkgmap.osmstyle.function;
+
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Locale;
+import java.util.regex.Pattern;
+
+import uk.me.parabola.mkgmap.reader.osm.Element;
+
+/**
+ * Returns the maxspeed converted to km/h.
+ * @author WanMil
+ */
+public class MaxSpeedKmhFunction extends CachedFunction {
+	private static final Pattern ENDS_IN_MPH_PATTERN = Pattern.compile(".*mph");
+	private static final Pattern REMOVE_MPH_PATTERN = Pattern.compile("[ \t]*mph");
+	private static final Pattern REMOVE_KMH_PATTERN = Pattern.compile("[ \t]*kmh");
+
+	private final DecimalFormat nf = new DecimalFormat("0.0#", DecimalFormatSymbols.getInstance(Locale.US));
+
+	public MaxSpeedKmhFunction() {
+		// requires maxspeed
+		super("maxspeed");
+	}
+
+	protected String calcImpl(Element el) {
+		// get the maxspeed value
+		String tagValue = el.getTag("maxspeed");
+		if (tagValue == null) {
+			// there is no maxspeed => function has no value
+			return null;
+		}
+		
+		String speedTag = tagValue.toLowerCase().trim();
+		
+		double factor = 1.0;
+		if (ENDS_IN_MPH_PATTERN.matcher(speedTag).matches()) {
+			// Check if it is a limit in mph
+			speedTag = REMOVE_MPH_PATTERN.matcher(speedTag).replaceFirst("");
+			factor = 1.61;
+		} else
+			speedTag = REMOVE_KMH_PATTERN.matcher(speedTag).replaceFirst("");  // get rid of kmh just in case
+
+		double kmh;
+		try {
+			kmh = Integer.parseInt(speedTag) * factor;
+		} catch (Exception e) {
+			// parse error => maxspeed cannot be calculated
+			return null;
+		}		
+		
+		// format with two decimals
+		return nf.format(kmh);
+	}
+
+	public String getName() {
+		return "maxspeedkmh";
+	}
+
+	public boolean supportsWay() {
+		return true;
+	}
+}
Index: src/uk/me/parabola/mkgmap/osmstyle/function/LengthFunction.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/function/LengthFunction.java	(revision 2673)
+++ src/uk/me/parabola/mkgmap/osmstyle/function/LengthFunction.java	(working copy)
@@ -80,10 +80,6 @@
 		return "length";
 	}
 
-	public String toString() {
-		return getName() + "()";
-	}
-
 	public boolean supportsWay() {
 		return true;
 	}
Index: src/uk/me/parabola/mkgmap/osmstyle/function/FunctionFactory.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/function/FunctionFactory.java	(revision 2673)
+++ src/uk/me/parabola/mkgmap/osmstyle/function/FunctionFactory.java	(working copy)
@@ -38,6 +38,8 @@
 		}
 		if ("area_size".equals(name))
 			return new AreaSizeFunction();
+		if ("maxspeedkmh".equals(name))
+			return new MaxSpeedKmhFunction();
 		
 		return null;
 	}
