diff --git a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
index 2a549f8..87ccccd 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
@@ -25,6 +25,8 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
+import java.util.regex.Pattern;
+
 import uk.me.parabola.imgfmt.app.Area;
 import uk.me.parabola.imgfmt.app.Coord;
 import uk.me.parabola.imgfmt.app.CoordNode;
@@ -53,6 +55,8 @@ import uk.me.parabola.mkgmap.reader.osm.Rule;
 import uk.me.parabola.mkgmap.reader.osm.Style;
 import uk.me.parabola.mkgmap.reader.osm.Way;
 
+import uk.me.parabola.mkgmap.reader.polish.PolishMapDataSource;
+
 /**
  * Convert from OSM to the mkgmap intermediate format using a style.
  * A style is a collection of files that describe the mappings to be used
@@ -144,6 +148,85 @@ public class StyledConverter implements OsmConverter {
 			lineAdder = overlayAdder;
 	}
 
+	private static Pattern commaPattern = Pattern.compile(",");
+
+	public GType makeGTypeFromTags(Element element) {
+		String[] vals = commaPattern.split(element.getTag("mkgmap:gtype"));
+
+		if(vals.length < 3) {
+			log.error("OSM element " + element.getId() + " has bad mkgmap:gtype value (should be 'kind,code,minres,[maxres],[roadclass],[roadspeed])");
+			log.error("  where kind is " + GType.POINT + "=point, " + GType.POLYLINE + "=polyline, " + GType.POLYGON + "=polygon");
+			return null;
+		}
+
+		element.setName(PolishMapDataSource.unescape(element.getTag("name")));
+
+		for(int i = 0; i < vals.length; ++i)
+			vals[i] = vals[i].trim();
+
+		int kind = 0;
+		try {
+			kind = Integer.decode(vals[0]);
+		}
+		catch (NumberFormatException nfe) {
+			log.error("OSM element " + element.getId() + " has bad value for kind: " + vals[0]);
+			return null;
+		}
+
+		if(kind != GType.POINT &&
+		   kind != GType.POLYLINE &&
+		   kind != GType.POLYGON) {
+			log.error("OSM element " + element.getId() + " has bad value for kind, is " + kind + " but should be " + GType.POINT + ", " + GType.POLYLINE + " or " + GType.POLYGON);
+			return null;
+		}
+
+		try {
+			Integer.decode(vals[1]);
+		}
+		catch (NumberFormatException nfe) {
+			log.error("OSM element " + element.getId() + " has bad value for type: " + vals[1]);
+			return null;
+		}
+
+		GType gt = new GType(kind, vals[1]);
+
+		try {
+			gt.setMinResolution(Integer.decode(vals[2]));
+		}
+		catch (NumberFormatException nfe) {
+			log.error("OSM element " + element.getId() + " has bad value for minres: " + vals[2]);
+		}
+
+		if(vals.length >= 4 && vals[3].length() > 0) {
+			try {
+				gt.setMaxResolution(Integer.decode(vals[3]));
+			}
+			catch (NumberFormatException nfe) {
+				log.error("OSM element " + element.getId() + " has bad value for maxres tag: " + vals[3]);
+			}
+		}
+
+		if(vals.length >= 5 && vals[4].length() > 0) {
+			try {
+				gt.setRoadClass(Integer.decode(vals[4]));
+			}
+			catch (NumberFormatException nfe) {
+				log.error("OSM element " + element.getId() + " has bad value for roadclass: " + vals[4]);
+			}
+		}
+
+		if(vals.length >= 6 && vals[5].length() > 0) {
+			try {
+				gt.setRoadClass(Integer.decode(vals[5]));
+			}
+			catch (NumberFormatException nfe) {
+				log.error("OSM element " + element.getId() + " has bad value for roadspeed: " + vals[5]);
+			}
+		}
+
+		return gt;
+	}
+
 	/**
 	 * This takes the way and works out what kind of map feature it is and makes
 	 * the relevant call to the mapper callback.
@@ -157,13 +240,21 @@ public class StyledConverter implements OsmConverter {
 		if (way.getPoints().size() < 2)
 			return;
 
-		preConvertRules(way);
+		GType foundType = null;
+		if(way.getTag("mkgmap:gtype") != null) {
+			foundType = makeGTypeFromTags(way);
+			if(foundType == null)
+				return;
+		}
+		else {
+			preConvertRules(way);
 
-		GType foundType = wayRules.resolveType(way);
-		if (foundType == null)
-			return;
+			foundType = wayRules.resolveType(way);
+			if (foundType == null)
+				return;
 
-		postConvertRules(way, foundType);
+			postConvertRules(way, foundType);
+		}
 
 		if (foundType.getFeatureKind() == GType.POLYLINE) {
 		    if(foundType.isRoad())
@@ -182,13 +273,22 @@ public class StyledConverter implements OsmConverter {
 	 * @param node The node to convert.
 	 */
 	public void convertNode(Node node) {
-		preConvertRules(node);
 
-		GType foundType = nodeRules.resolveType(node);
-		if (foundType == null)
-			return;
+		GType foundType = null;
+		if(node.getTag("mkgmap:gtype") != null) {
+			foundType = makeGTypeFromTags(node);
+			if(foundType == null)
+				return;
+		}
+		else {
+			preConvertRules(node);
 
-		postConvertRules(node, foundType);
+			foundType = nodeRules.resolveType(node);
+			if (foundType == null)
+				return;
+
+			postConvertRules(node, foundType);
+		}
 
 		addPoint(node, foundType);
 	}
diff --git a/src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java b/src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java
index afda875..d2dc657 100644
--- a/src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java
+++ b/src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java
@@ -397,7 +397,7 @@ public class PolishMapDataSource extends MapperBasedMapDataSource implements Loa
 	 * @param s The original string that may contain codes.
 	 * @return A string with the escape codes replaced by the single character.
 	 */
-	private String unescape(String s) {
+	public static String unescape(String s) {
 		int ind = s.indexOf("~[");
 		if (ind < 0)
 			return s;
