You can use the <oneWayArrow> element to define an arrow symbol to be drawn to show the direction of one-way streets. The <oneWayArrow> attributes are:

  • fill: the color used to draw the arrow.
  • border: if specified, a border is drawn in this color.
  • borderWidth: the width of the border in user units: by default, 1024 units are equal to the width of the road, but you can set the unit size to whatever you like using the unitsPerLineWidth attribute (see below).
  • color: if specified, a color to be used to colorize any SVG icon used as the arrow.
  • gap: the gap between the left edges of successive symbols, in user units, where 1024 units equal the width of the road (unless modified by unitsPerLineWidth); default value = 1024.
  • id:  if SVG is used to define the graphics (see below)the identifying name of the icon.
  • isLabel: allowed values are 'yes' and 'no'; the default is 'no'. If the value is 'yes', this attribute treats arrows as labels, which means that they are drawn just after the object's label and will not overlap other labels in the same label layer, or other arrows with the 'isLabel' attribute.
  • maxScale: the maximum scale factor at which the symbols are drawn. The default is 10000.
  • opacity: the opacity used for the fill color.
  • path: a path, defined using SVG path data syntax (the 'd' attribute in the element), defining the arrow or other symbol, in a coordinate system where the direction of the road is from left to right and the width of the road is 1024 units, unless modified by unitsPerLineWidth.
  • ref: the name of an arrow icon to be drawn; the icon must have been defined in a <defs> element earlier in the style sheet.
  • unitsPerLineWidth: the number of units in the path definition that are equal to the width of the road. The default value is 1024.
  • width: if SVG is used to define the graphics (see below), the width of the graphics. The default value is the width of the road, and percentages also refer to the width of the road.
  • height: if SVG is used to define the graphics (see below), the height of the graphics. The default value is the width of the road, or (if the width attribute was used) the same value as the width. Percentages refer to the width of the road.

Example: a broad transparent yellow arrow:

<oneWayArrow path="M 0 50 H 300 L 40 300 H 180 L 505 0 L 180 -300 H 40 L 300 -50 H 0 Z" fill="yellow" opacity="0.5"/>

If you use <oneWayArrow> on a layer other than "road" it is treated as meaning <repeatedSymbol> and the symbols are unconditionally drawn along the path in the direction in which it is defined.

Using SVG for arrows

For more complex arrow graphics, where a filled shape with an optional border is not enough, use SVG, You can do it like this:

 <oneWayArrow gap='2500' opacity='1' isLabel='yes'>
   <svg x='-500' y='-500' width='1000' height='1000'>
      <linearGradient id="XXX" gradientUnits="userSpaceOnUse" x1="-500" y1="0" x2="1000" y2="0">
         <stop offset="0" stop-color='pink'/>
         <stop offset="1" stop-color='red'/>
    <path fill='url(#XXX)' d='M -450 -50 V 50 H 250 L -100 400 H 50 L 450 0 L 50 -400 H -100 L 250 -50 H -450 Z' />

which produces arrows that fade from red to pink along their length.

You can also define the arrow icon in the <defs> section and reference it using the ref attribute.


Repeated symbols and start and end symbols on lines

You can draw repeated symbols along any linear feature. For example, national frontiers are sometimes emphasized using small crosses, and cross-ties can be drawn along railway lines. The attributes you can use are exactly the same as for the oneWayArrow element, except that you use repeatedSymbol instead of oneWayArrow. You cannot use both oneWayArrow and repeatedSymbol for a road.

This feature can be used to place arrows along route lines overlaid on the map by means of of an auxiliary map database.

Using SVG for repeated symbols

You can use SVG to define repeated symbols in exactly the same way as for one-way arrows.

Start and end symbols

Symbols can also be specified for the starts and ends of lines. The startSymbol and endSymbol elements work in the same way as oneWayArrow and repeatedSymbol and allow you to create graphics that is drawn at the start or end of a line only. This can be used for arrow-heads, transverse ticks, and the like.


Dashed, truncated and extended lines

Dashed lines are specified using a syntax similar to that of SVG. Use the attribute dashArray in the <line> or <shape> tag. The value is a comma-separated list of dash and gap sizes, relative to the line width (e.g., the value 2 means a dash or gap twice as long as the line width).

The railway line below is drawn as a dashed line with a border, using this code in the style sheet:

<layer name='railway'>
<line width='12m,2pt' border='grey' borderWidth='10%,0.7,2' fill='white' dashArray='5,5'/>
<label font-size='75%,8pt' glow='white' color='black' case='assume-title'/>

White dashes are drawn over a grey border; when there are dashes, the border is also the colour between the dashes.

dashed railway

Truncating and extending lines

Sometimes lines need to be truncated at the start or end or both. For example, a line indicating an airway may need to be shortened so that it doesn't interfere with symbols for navigation aids or position fixes. You can use the truncationAtStart and truncationAtEnd attributes inside <line> or <highlight> elements to shorten lines. All the normal map-related or display-related dimensions can be used, and you can also use percentages, which refer to the width of the line.

Negative values have the effect of extending lines. This can be used to join disconnected sections of highlights drawn along lines (for example, to show traffic density on roads).


Map objects in a single layer often have different attributes. For instance, roads are distinguished by their feature type and by other attributes indicating whether a road is one-way, private, etc. These attributes affect the way the road is drawn.

You use <condition> sections inside <layer> to treat objects with differing attributes in different ways. Each <condition> section is like an embedded <layer> section for only those objects with the specified attributes.

A <condition> section inherits all attributes defined in the containing <layer>, unless it is nested inside another condition, in which case it inherits from the containing condition. Conditions may be nested up to 15 levels deep.

You set the actual condition using a style sheet expression in the exp attribute. Expressions test integer and string attributes of map objects; if the expression is true, the object is drawn using the styles given inside the condition element

This is hard to understand without an example. Here is the mid-level road layer from the standard style sheet:

<layer name='road/mid' road='true'>
    <condition exp='@feature_type="tertiary road"'>
        <line border='dimgrey' borderWidth='8%,0.35pt,1pt' fill='orange+khaki+0.8white' width='10m@6000_40m@40000,0.3pt'/>
         <macro ref='minor-road-label'/>
         <macro color='darkkhaki' ref='one-way-arrow'/>
         <macro ref='standard-bridge'/>
         <macro ref='grey-tunnel'/>
    <condition exp='@feature_type in { "secondary road", "secondary road link" }'>
        <line border='dimgrey' borderWidth='8%,0.35pt,1pt' fill='orange+khaki+0.6white' width='10m@6000_40m@40000,0.6pt'/>
        <scale max='40000'>
            <label case='assume-title' color='dimgrey' font-size='75%,5pt,18pt' glow='white' glowWidth='7%,0.5pt' labelFormat=';int_name;name:en+" "ref' maxScale='75000'/>
        <macro color='darkkhaki+black' ref='one-way-arrow'/>
        <macro ref='standard-bridge'/>
        <macro ref='standard-tunnel'/>

The first condition has the test '@feature_type="tertiary road"', meaning that only tertiary roads are drawn by the specifications in this condition.

Here is an example showing the inheritance of attributes from the containing layer:

<layer name='waterway/minor'>
    <label case='assume-title' color='ncsblue' duplicate='1000m,512pt' font-family='serif' font-style='italic' glow='white' glowWidth='7%,0.5pt' position='centralpath' priority='1'/>
    <line fill='lightblue'/>
    <shape fill='lightblue'/>
    <condition exp='@feature_type="str"'>
        <line width='4m,0.3pt'/>
        <label font-size='75%,5pt,18pt'/>
    <condition exp='@feature_type="dra"'>
        <line width='2m,0.3pt'/>
        <label font-size='75%,5pt,18pt'/>
    <macro ref='water-minor'/>

And here is an example of nested conditions:

<layer name='pushpin'>
    <label case='assume-title' color='ncsred' colorAttrib='_color' font-size='12m,6pt,12pt' glow='white' glowWidth='7%,0.5pt' priority='-20' wrapWidth='5em'/>
    <condition exp='@=0'>
        <condition exp='_iconText'>
            <icon textAttrib='_iconText' font-size='24m,12pt,72pt' color='ncsred' colorAttrib='_color' canOverlap='true'/>
        <condition exp='!_iconText'>
            <icon ref='pushpin-icon' color='ncsred' colorAttrib='_color' canOverlap='yes' canCombine='yes'/>
            <condition exp='_combined gt 1'>
                <icon ref='large-pushpin-icon' color='ncsred'/>
                <label position='icon' labelFormat='_combined' color='ncsred' colorAttrib='_color' font-size='12m,6pt,12pt' glow='white' glowWidth='7%,1' priority='-21' wrapWidth='5em'/>
    <condition exp='@!=0'>
        <shape border='ncsred' borderWidth='2m,0.6pt' fill='ncsred' opacity='0.5'/>
        <line fill='ncsred' opacity='0.5' width='5m,0.6pt'/>

Here, the outer two conditions distinguish point pushpin objects ('@=0'; @ is the type, and 0 means a point; 1 means a line, 2 a polygon and 3 an array or texture) from others. Within point objects, those with an _iconText attribute are treated differently from those without, and pushpins without _iconText are drawn using a larger icon if they are the result of combining several pushpins.

When the map is drawn, objects are matched to the innermost test that succeeds.


There are 32 route types, which are a subset of the many feature type values. They can all be tested in style sheet expressions. For example, the expression '@feature_type = "primary road' tests whether a map object is a primary road. The route types are:

  • motorway
  • motorway link
  • trunk road
  • trunk link
  • primary road
  • primary link
  • secondary road
  • secondary link
  • tertiary toad
  • unclassified road
  • residential road
  • track
  • service road
  • pedestrian road
  • vehicular ferry
  • passenger ferry
  • living street
  • cycleway
  • path
  • footway
  • bridleway
  • steps
  • other road
  • unpaved road
  • railway
  • light rail
  • subway
  • aerialway
  • ski downhill
  • ski nordic
  • waterway
  • unknown route

Every map object has a Feature Type, which is part of its Feature Info value, which is encoded as a 32-bit integer.

You don't have to work with actual numeric values. In style sheet expressions you can test the name, or (if the feature type is not a route type) the three-letter code. The following expressions mean the same:

'@feature_type = "uni"'
'@feature_type = "university"'

The feature types consist of the 32 route types 0...31, and other types, which are created from three-letter codes aaa ... zzz by encoding each letter in five bits, using the values 1...26 for the letters a...z. Here is a C++ function to create a feature code from three lower-case letters:

inline uint32_t constexpr FeatureTypeCode(int A,int B,int C)
    return (char(A - 'a' + 1) << 10) | (char(B - 'a' + 1) << 5) | (char(C - 'a' + 1));

Here are the feature types that are currently defined and which may be used in expressions in makemap rules (.makemap files), and in style sheet conditions:

 Motorway = 0,
 MotorwayLink = 1,
 TrunkRoad = 2,
 TrunkLink = 3,
 PrimaryRoad = 4,
 PrimaryLink = 5,
 SecondaryRoad = 6,
 SecondaryLink = 7,
 TertiaryRoad = 8,
 UnclassifiedRoad = 9,
 ResidentialRoad = 10,
 Track = 11,
 ServiceRoad = 12,
 PedestrianRoad = 13,
 VehicularFerry = 14,
 PassengerFerry = 15,
 LivingStreet = 16,
 Cycleway = 17,
 Path = 18,
 Footway = 19,
 Bridleway = 20,
 Steps = 21,
 OtherRoad = 22,
 UnpavedRoad = 23,
 Railway = 24,
 LightRail = 25,
 Subway = 26,
 AerialWay = 27,
 SkiDownhill = 28,
 SkiNordic = 29,
 Waterway = 30,
 UnknownRoute = 31,
 UnknownNonRoute = 32,
 AdminArea1 = FeatureTypeCode('a','a','a'),
 AdminArea2 = FeatureTypeCode('a','a','b'),
 AdminArea3 = FeatureTypeCode('a','a','c'),
 AdminArea4 = FeatureTypeCode('a','a','d'),
 AdminArea5 = FeatureTypeCode('a','a','e'),
 AdminArea6 = FeatureTypeCode('a','a','f'),
 AdminArea7 = FeatureTypeCode('a','a','g'),
 AdminArea8 = FeatureTypeCode('a','a','h'),
 AdminArea9 = FeatureTypeCode('a','a','i'),
 AdminArea10 = FeatureTypeCode('a','a','j'),
 Address = FeatureTypeCode('a','d','d'),
 Aerodrome = FeatureTypeCode('a','e','r'),
 Airport = FeatureTypeCode('a','i','r'),
 AirportGate = FeatureTypeCode('a','g','t'),
 AirportHoldingPosition = FeatureTypeCode('a','h','p'),
 Allotments = FeatureTypeCode('a','l','l'),
 AlpineHut = FeatureTypeCode('a','l','p'),
 AmbulanceStation = FeatureTypeCode('a','m','b'),
 Apron = FeatureTypeCode('a','p','r'),
 AerialWayPylon = FeatureTypeCode('a','p','y'),
 Artwork = FeatureTypeCode('a','r','t'),
 AerialWayStation = FeatureTypeCode('a','s','t'),
 AirTerminal = FeatureTypeCode('a','t','e'),
 Atm = FeatureTypeCode('a','t','m'),
 Attraction = FeatureTypeCode('a','t','t'),
 Bar = FeatureTypeCode('b','a','r'),
 Basin = FeatureTypeCode('b','a','s'),
 Bay = FeatureTypeCode('b','a','y'),
 Beach = FeatureTypeCode('b','e','a'),
 Beacon = FeatureTypeCode('b','e','c'),
 BedAndBreakfast = FeatureTypeCode('b','e','d'),
 Bench = FeatureTypeCode('b','e','n'),
 Bank = FeatureTypeCode('b','n','k'),
 Boatyard = FeatureTypeCode('b','o','a'),
 Borough = FeatureTypeCode('b','o','r'),
 Boundary = FeatureTypeCode('b','o','u'),
 BicycleParking = FeatureTypeCode('b','p','k'),
 BicycleRental = FeatureTypeCode('b','r','e'),
 BareRock = FeatureTypeCode('b','r','c'),
 Barracks = FeatureTypeCode('b','r','k'),
 BrownField = FeatureTypeCode('b','r','o'),
 BusStop = FeatureTypeCode('b','s','p'),
 BusStation = FeatureTypeCode('b','s','t'),
 BufferStop = FeatureTypeCode('b','u','f'),
 Building = FeatureTypeCode('b','u','i'),
 Bunker = FeatureTypeCode('b','u','n'),
 Cabin = FeatureTypeCode('c','a','b'),
 Cafe = FeatureTypeCode('c','a','f'),
 CampSite = FeatureTypeCode('c','a','m'),
 Canal = FeatureTypeCode('c','a','n'),
 CaveEntrance = FeatureTypeCode('c','a','v'),
 CableCar = FeatureTypeCode('c','c','r'),
 CableDistributionCabinet = FeatureTypeCode('c','d','c'),
 Cemetery = FeatureTypeCode('c','e','m'),
 ChairLift = FeatureTypeCode('c','h','a'),
 CheckPoint = FeatureTypeCode('c','h','e'),
 Chalet = FeatureTypeCode('c','h','l'),
 CivilBoundary = FeatureTypeCode('c','i','b'),
 Cinema = FeatureTypeCode('c','i','n'),
 City = FeatureTypeCode('c','i','t'),
 Cliff = FeatureTypeCode('c','l','f'),
 Clinic = FeatureTypeCode('c','l','i'),
 Commercial = FeatureTypeCode('c','m','r'),
 Coastline = FeatureTypeCode('c','o','a'),
 College = FeatureTypeCode('c','o','l'),
 Common = FeatureTypeCode('c','o','m'),
 Construction = FeatureTypeCode('c','n','s'),
 Conservation = FeatureTypeCode('c','n','v'),
 Continent = FeatureTypeCode('c','o','n'),
 County = FeatureTypeCode('c','o','u'),
 CarPark = FeatureTypeCode('c','p','k'),
 CarRental = FeatureTypeCode('c','r','e'),
 Crossing = FeatureTypeCode('c','r','o'),
 Country = FeatureTypeCode('c','r','y'),
 CarSharing = FeatureTypeCode('c','s','h'),
 CutLine = FeatureTypeCode('c','u','t'),
 CarWash = FeatureTypeCode('c','w','a'),
 CaravanSite = FeatureTypeCode('c','v','n'),
 CyclingRoute = FeatureTypeCode('c','y','r'),
 Dam = FeatureTypeCode('d','a','m'),
 DangerArea = FeatureTypeCode('d','a','n'),
 Dentist = FeatureTypeCode('d','e','n'),
 Disused = FeatureTypeCode('d','i','s'),
 Ditch = FeatureTypeCode('d','i','t'),
 Dock = FeatureTypeCode('d','o','c'),
 DogPark = FeatureTypeCode('d','o','g'),
 Drain = FeatureTypeCode('d','r','a'),
 DragLift = FeatureTypeCode('d','r','g'),
 Doctors = FeatureTypeCode('d','r','s'),
 District = FeatureTypeCode('d','s','t'),
 ElectricVehicleCharging = FeatureTypeCode('e','v','c'),
 Farm = FeatureTypeCode('f','a','r'),
 FarmYard = FeatureTypeCode('f','a','y'),
 Fell = FeatureTypeCode('f','e','l'),
 FerryTerminal = FeatureTypeCode('f','e','t'),
 FastFood = FeatureTypeCode('f','f','d'),
 FireExtinguisher = FeatureTypeCode('f','i','e'),
 FireFlapper = FeatureTypeCode('f','i','f'),
 FireHose = FeatureTypeCode('f','i','h'),
 FireStation = FeatureTypeCode('f','i','s'),
 FitnessStation = FeatureTypeCode('f','i','t'),
 FireHydrant = FeatureTypeCode('f','i','y'),
 Forestry = FeatureTypeCode('f','o','r'),
 Fishing = FeatureTypeCode('f','s','h'),
 Fuel = FeatureTypeCode('f','u','e'),
 Funicular = FeatureTypeCode('f','u','n'),
 Garages = FeatureTypeCode('g','a','r'),
 Gate = FeatureTypeCode('g','a','t'),
 Garden = FeatureTypeCode('g','d','n'),
 Generator = FeatureTypeCode('g','e','n'),
 GreenHouse = FeatureTypeCode('g','h','o'),
 Glacier = FeatureTypeCode('g','l','a'),
 GolfCourse = FeatureTypeCode('g','o','l'),
 Gondola = FeatureTypeCode('g','o','n'),
 GoodsAerialWay = FeatureTypeCode('g','o','o'),
 Grass = FeatureTypeCode('g','r','a'),
 GreenField = FeatureTypeCode('g','r','e'),
 GritBin = FeatureTypeCode('g','r','b'),
 GraveYard = FeatureTypeCode('g','r','y'),
 GuestHouse = FeatureTypeCode('g','u','e'),
 Halt = FeatureTypeCode('h','a','l'),
 Hamlet = FeatureTypeCode('h','a','m'),
 Hangar = FeatureTypeCode('h','a','n'),
 Heath = FeatureTypeCode('h','e','a'),
 Helipad = FeatureTypeCode('h','e','l'),
 RailwayHalt = FeatureTypeCode('h','l','t'),
 HikingRoute = FeatureTypeCode('h','i','k'),
 HorseRiding = FeatureTypeCode('h','o','r'),
 Hospital = FeatureTypeCode('h','o','s'),
 Hotel = FeatureTypeCode('h','o','t'),
 HorseRidingRoute = FeatureTypeCode('h','r','r'),
 Hostel = FeatureTypeCode('h','s','t'),
 IceRink = FeatureTypeCode('i','c','e'),
 Industrial = FeatureTypeCode('i','n','d'),
 Information = FeatureTypeCode('i','n','f'),
 Island = FeatureTypeCode('i','s','l'),
 IsolatedDwelling = FeatureTypeCode('i','s','o'),
 Junction = FeatureTypeCode('j','c','t'),
 Kindergarten = FeatureTypeCode('k','i','n'),
 LandFill = FeatureTypeCode('l','a','n'),
 Land = FeatureTypeCode('l','n','d'),
 LevelCrossing = FeatureTypeCode('l','e','v'),
 Library = FeatureTypeCode('l','i','b'),
 Locality = FeatureTypeCode('l','o','c'),
 LockGate = FeatureTypeCode('l','o','k'),
 MaritimeBoundary = FeatureTypeCode('m','a','b'),
 Mall = FeatureTypeCode('m','a','l'),
 Marsh = FeatureTypeCode('m','a','r'),
 Meadow = FeatureTypeCode('m','e','a'),
 Military = FeatureTypeCode('m','i','l'),
 Marina = FeatureTypeCode('m','n','a'),
 Motel = FeatureTypeCode('m','o','t'),
 MinorPowerLine = FeatureTypeCode('m','p','l'),
 MiniatureGolf = FeatureTypeCode('m','r','g'),
 MiniatureRailway = FeatureTypeCode('m','r','y'),
 Mud = FeatureTypeCode('m','u','d'),
 Municipality = FeatureTypeCode('m','u','n'),
 Museum = FeatureTypeCode('m','u','s'),
 NatureReserve = FeatureTypeCode('n','a','t'),
 NationalPark = FeatureTypeCode('n','a','p'),
 NavalBase = FeatureTypeCode('n','a','v'),
 Neighborhood = FeatureTypeCode('n','e','i'),
 NursingHome = FeatureTypeCode('n','u','r'),
 Orchard = FeatureTypeCode('o','r','c'),
 PrecisionApproachPathIndicator = FeatureTypeCode('p','a','p'),
 Park = FeatureTypeCode('p','a','r'),
 PublicBuilding = FeatureTypeCode('p','b','u'),
 PostBox = FeatureTypeCode('p','b','x'),
 PostCode = FeatureTypeCode('p','c','o'),
 PicnicTable = FeatureTypeCode('p','c','t'),
 Peak = FeatureTypeCode('p','e','a'),
 Pharmacy = FeatureTypeCode('p','h','a'),
 Phone = FeatureTypeCode('p','h','o'),
 PicnicSite = FeatureTypeCode('p','i','c'),
 Pier = FeatureTypeCode('p','i','e'),
 Pipeline = FeatureTypeCode('p','i','p'),
 ParkingEntrance = FeatureTypeCode('p','k','e'),
 Parking = FeatureTypeCode('p','k','g'),
 ParkingSpace = FeatureTypeCode('p','k','s'),
 PlantNursery = FeatureTypeCode('p','l','a'),
 Platform = FeatureTypeCode('p','l','f'),
 PlaceOfWorship = FeatureTypeCode('p','l','w'),
 Playground = FeatureTypeCode('p','l','y'),
 PostOffice = FeatureTypeCode('p','o','f'),
 Police = FeatureTypeCode('p','o','l'),
 Position = FeatureTypeCode('p','o','s'),
 ProtectedArea = FeatureTypeCode('p','r','a'),
 PowerSubStation = FeatureTypeCode('p','s','s'),
 Pub = FeatureTypeCode('p','u','b'),
 PowerLine = FeatureTypeCode('p','w','l'),
 PowerStation = FeatureTypeCode('p','w','s'),
 Quarry = FeatureTypeCode('q','a','r'),
 Quarter = FeatureTypeCode('q','r','t'),
 Range = FeatureTypeCode('r','a','n'),
 Rapids = FeatureTypeCode('r','a','p'),
 Recycling = FeatureTypeCode('r','c','y'),
 RecreationGround = FeatureTypeCode('r','e','c'),
 Reef = FeatureTypeCode('r','e','e'),
 Region = FeatureTypeCode('r','e','g'),
 Retail = FeatureTypeCode('r','e','t'),
 Ridge = FeatureTypeCode('r','i','j'),
 River = FeatureTypeCode('r','i','v'),
 Rock = FeatureTypeCode('r','o','c'),
 RoundHouse = FeatureTypeCode('r','o','u'),
 ResidentialArea = FeatureTypeCode('r','s','d'),
 Restaurant = FeatureTypeCode('r','s','t'),
 Reservoir = FeatureTypeCode('r','s','v'),
 Runway = FeatureTypeCode('r','u','n'),
 Route = FeatureTypeCode('r','u','t'),
 RiverBank = FeatureTypeCode('r','v','b'),
 SaltPond = FeatureTypeCode('s','a','l'),
 Sand = FeatureTypeCode('s','a','n'),
 Sauna = FeatureTypeCode('s','a','u'),
 School = FeatureTypeCode('s','c','h'),
 Scree = FeatureTypeCode('s','c','r'),
 Scrub = FeatureTypeCode('s','c','b'),
 Sea = FeatureTypeCode('s','e','a'),
 StateEmergencyServiceStation = FeatureTypeCode('s','e','s'),
 Shop = FeatureTypeCode('s','h','o'),
 SkiRoute = FeatureTypeCode('s','k','r'),
 Slipway = FeatureTypeCode('s','l','i'),
 SportsCenter = FeatureTypeCode('s','p','o'),
 SportsPitch = FeatureTypeCode('s','p','p'),
 Spring = FeatureTypeCode('s','p','r'),
 SportsTrack = FeatureTypeCode('s','p','t'),
 State = FeatureTypeCode('s','t','a'),
 Stadium = FeatureTypeCode('s','t','m'),
 RailwayStation = FeatureTypeCode('s','t','n'),
 Station = FeatureTypeCode('s','t','n'), // deliberate duplicate
 Stone = FeatureTypeCode('s','t','o'),
 StopPosition = FeatureTypeCode('s','t','p'),
 Stream = FeatureTypeCode('s','t','r'),
 Strait = FeatureTypeCode('s','t','t'),
 Suburb = FeatureTypeCode('s','u','b'),
 Supermarket = FeatureTypeCode('s','u','p'),
 SurveyPoint = FeatureTypeCode('s','u','r'),
 SubwayEntrance = FeatureTypeCode('s','w','e'),
 SwimmingPool = FeatureTypeCode('s','w','i'),
 Tank = FeatureTypeCode('t','a','n'),
 Taxi = FeatureTypeCode('t','a','x'),
 Theatre = FeatureTypeCode('t','h','e'),
 ThemePark = FeatureTypeCode('t','h','p'),
 Toilet = FeatureTypeCode('t','o','i'),
 Town = FeatureTypeCode('t','o','w'),
 TurningCircle = FeatureTypeCode('t','c','i'),
 TurningPoint = FeatureTypeCode('t','p','t'),
 Tram = FeatureTypeCode('t','r','a'),
 Tree = FeatureTypeCode('t','r','e'),
 TrafficSignals = FeatureTypeCode('t','r','f'),
 TrackPoint = FeatureTypeCode('t','r','p'),
 TreeRow = FeatureTypeCode('t','r','r'),
 TramStop = FeatureTypeCode('t','r','s'),
 TurnTable = FeatureTypeCode('t','u','r'),
 Tower = FeatureTypeCode('t','w','r'),
 Taxiway = FeatureTypeCode('t','w','y'),
 University = FeatureTypeCode('u','n','i'),
 VisualApproachSlopeIndicator = FeatureTypeCode('v','a','s'),
 VillageGreen = FeatureTypeCode('v','i','g'),
 Village = FeatureTypeCode('v','i','l'),
 Vineyard = FeatureTypeCode('v','i','n'),
 ViewPoint = FeatureTypeCode('v','i','w'),
 Volcano = FeatureTypeCode('v','o','l'),
 Waterfall = FeatureTypeCode('w','a','f'),
 WaterPark = FeatureTypeCode('w','a','p'),
 Water = FeatureTypeCode('w','a','t'),
 Weir = FeatureTypeCode('w','e','r'),
 Wetland = FeatureTypeCode('w','e','t'),
 Windsock = FeatureTypeCode('w','i','s'),
 WalkingRoute = FeatureTypeCode('w','l','k'),
 Wood = FeatureTypeCode('w','o','o'),
 Works = FeatureTypeCode('w','o','r'),
 Waypoint = FeatureTypeCode('w','p','t'),
 WaterTower = FeatureTypeCode('w','t','t'),
 WaterWell = FeatureTypeCode('w','t','w'),
 Zoo = FeatureTypeCode('z','o','o'),
// legacy types for backward compatibility
 LegacyBridleway = FeatureTypeCode('b','r','i'),
 LegacyCycleway = FeatureTypeCode('c','y','c'),
 LegacyFootway = FeatureTypeCode('f','o','o'),
 LegacyLightRail = FeatureTypeCode('l','i','r'),
 LegacyMonorail = FeatureTypeCode('m','o','n'),
 LegacyNarrowGauge = FeatureTypeCode('n','a','r'),
 LegacyPreservedRailway = FeatureTypeCode('p','r','y'),
 LegacyRailway = FeatureTypeCode('r','l','y'),
 LegacySteps = FeatureTypeCode('s','t','e'),
 LegacySubway = FeatureTypeCode('s','w','y'),
 LegacyTram = FeatureTypeCode('t','r','a'),
 Invalid = INT16_MAX


This release, 8.6, was made on 8th August 2023 and is based on commit 8.6-1-gc0939f76f in the Git repository.

The previous release, 8.4, was made on 20th February 2023 and was based on commit 8.4-1-gcb08c572d in the Git repository.

Online Map Data Access

New functionality allows CartoType to support both the client and server roles in using CTM1 files online. The Framework function

std::string HandleQuery(const std::string& aQuery,const std::string& aData)

can be used by servers to handle queries sent from client programs. A client program opens a map file using a URL instead of a filename. Any string starting with http: or https: is treated as a URL. Internally, requests for map data are passed to the server as HTTP requests which must be fulfilled using Framework::HandleQuery. The HandleQuery function is implemented in the C++ and .NET APIs, allowing servers to be written using C++, C#, or another .NET language. The client program can run on any CartoType platform. This allows CartoType applications to use very large maps without the need to install the map data on a device.

Address Searching

Address searching has been greatly simplified internally, and made more accurate and more likely to find an address, and there are some public API changes. Specific functions for finding street addresses, parts of addresses and buildings near streets have been abolished. Address searches are more likely to be successful if CTM1 files are re-created using the new version of makemap, which creates CTM1 8.2 data rather than CTM1 8.1.
overlapping maps

Clipping of overlapping maps is no longer supported. It did not work properly and was hardly ever used. If maps are loaded as tiles, side by side, they should not overlap. Of course overlapping maps are allowed, and useful, if different maps have different types of data and are intended to be used as overlays.

Framework Creation

Framework objects can be created without style sheets. If an empty string is supplied as the style sheet, everything still works but maps cannot be drawn. This is useful when creating Framework objects for geocoding alone.
When a Framework object is created the default number of text and street index levels loaded is now 3 rather than 1, which uses more RAM but speeds up address searching.

Style Sheets

Style sheet expressions can now test the display size of objects by using units, as in the expression '@feature_type="isl" and @size gt 5mm', which tests for islands with a displayed size (maximum diagonal of bounding box) greater than five millimetres.


Map metadata now includes an array of the names of all the layers in the map.

Specific C++ SDK Changes

The function Framework::HandleQuery has been added to make it possible to write an on-line map data server using CartoType:

std::string Framework::HandleQuery(const std::string& aQuery,const std::string& aData);

The enum class AddressPart has been abolished.

The data member Layers, a vector of strings, has been added to the MapMetaData class.

FrameworkMapDataSet::LoadMapData no longer has the argument aMapOverlaps, and the MapsOverlap data member of FrameworkParam has been abolished.

These Framework functions have been abolished:

  • SetMapsOverlap
  • FindStreetAddresses
  • FindAddressPart
  • BuildingsNearStreet

Functions to load and append style sheets now take char*, not uint8_t*, as the type for the style sheet text.

CartoType's own list classes, formerly defined in cartotype_list.h, have been abolished.

For convenience, map object user data defined by the UserData union now includes a view of the data as a pair of two 32-bit integers.

Stream classes have been simplified. In particular, DataInputStream and DataOutputStream have been merged into InputStream and OutputStream. These changes should not affect users because these classes are mainly for internal use.

These functions have been added to MString:

  • Text Substring(size_t aStart,size_t aLength) const
  • void Replace(size_t aStart,size_t aEnd,const char16_t* aText,size_t aLength = npos)

RefCountedString is now immutable. It was formerly intended as such but that was not enforced.

Specific .NET SDK Changes

The function Framework.HandleQuery has been added to make it possible to write an on-line map data server using CartoType:

array<Byte>^ HandleQuery(String^ aQuery,array<Byte>^ aData)

These Framework functions have been abolished:

  • SetMapsOverlap
  • FindStreetAddresses
  • FindAddressPart
  • FindBuildingsNearStreet

The property Layers, a list of strings, has been added to the MapMetaData class.

The enum class AddressPart has been abolished.

The MapsOverlap property of FrameworkParam has been abolished.

Specific UWP SDK Changes

These Framework functions have been abolished:

  • SetMapsOverlap
  • FindStreetAddresses
  • FindAddressPart
  • FindBuildingsNearStreet

The property Layers, a vector of strings, has been added to the MapMetaData class.

The enum class AddressPart has been abolished.

The MapsOverlap property of FrameworkParam has been abolished.

Specific Android SDK Changes

These Framework methods have been abolished:

  • setMapsOverlap
  • findStreetAddresses
  • findAddressPart
  • findBuildingsNearStreet

The member 'layers', a vector of strings, has been added to the MapMetaData class.

The AddressPart class has been abolished.

The mapsOverlap member of FrameworkParam has been abolished.

The MapView class now uses a different scale gesture detector, for smoother and more reliable handling of pinch zoom gestures.

Specific iOS SDK Changes

These CartoTypeFramework methods have been abolished:

  • setMapsOverlap
  • findStreetAddresses
  • findAddressPart

The property 'layers', an array of strings, has been added to the CartoTypeMapMetaData class.

The CartoTypeFramework method readUrl has been added for internal use.

The CartoTypeAddressPart enum has been abolished.

The mapsOverlap member of CartoTypeFrameworkParam has been abolished.

Makemap Changes

Makemap now creates CTM1 files with a version of 8.2 rather than 8.1. The change is to the way search terms are stored in the text index. They are now stored as-is rather than being converted to lower-case, which allows for better matching in some cases. Older versions of CartoType can read CTM1 8.2 maps, and newer versions can read CTM1 8.1 maps. It is highly recommended to re-create CTM1 files using the new version of makemap if you use address searching, because certain streets cannot not be found and there are false positives using the older version. That is because strings encoding object IDs were erroneously converted to lower case, changing the value of the encoded numeric ID.

The option /textindex no longer includes the choice of making a partial text index. The choice is now only between a full text index and none.

Standard Style Sheet Changes

These are changes to the file standard.ctstyle.

The 'found' layer, used by the Maps App and the Windows Demo to display found objects, now uses a new icon called 'found-point-icon' to highlight point objects. It is a scalable circle icon, rather than the fixed-size circle formerly inserted.

The 'outline' layer now uses labels only for islands with a size (maximum length of diagonal of bounding box) of more than 5mm on the projected map. This rule uses the new ability of style sheet expressions to interpret numbers with trailing units, like '5mm', where appropriate.

The terrain layers 'terrain-height-feet' and 'terrain-shadow' are now suppressed at scales larger than 1:20000 (formerly 1:10000) because they became blocky at very large scales.

The layers 'place/major' and 'place/minor' now draw city, town and village labels only for point objects.

The layer 'land/major' now suppresses labels at scales smaller than 1:100,000.

The layer 'waterway/major' now draws labels only for features with a size (maximum length of diagonal of bounding box) greater than 1cm on the projected map.

The layer 'road/mid' now suppresses secondary road labels at scales smaller than 1:40,000 (formerly 1:75,000).

The layer 'road/major' now draws labels only for road segments with a size (maximum length of diagonal of bounding box) greater than 1cm on the projected map.

The layer 'routerelation', used for long-distance trails and cycle paths, now labels walking routes in green and cycling routes in blue.

If the style sheet variable DEBUG is set programmatically, the layers '_route', '_route1', '_route2' and 'postcode' are added to show route layers created in contraction hierarchy routing data and postcode boundaries and points. These layers are useful when investigating routing and address-finding issues.


This release, 8.4, was made on 20th February 2023 and is based on commit 8.4-1-gcb08c572d in the Git repository.

The previous release, 8.2, was made on 9th December 2022 and was based on commit 8.2-57-g51a9fa561 in the Git repository.

mapinfo is the new name for ctm1_info

The tool to describe the contents of a CartoType map file (a CTM1 file) is now called mapinfo, not ctm1_info. The new name is more descriptive and easier to type.

mapinfo usage and command line options are now:

usage :mapinfo { -option1 ... -optionN } <CartoType map file (CTM1 file) name>
        -d<layer>{,<condition>}: dumps all map objects in a layer,
            optionally using a condition to select objects
        -D<layer>{,<condition>}: like -d but also dumps coordinates
        -a<layer>{,<condition>}: like -d but gives combined area and length of objects only
        -e<W,S,E,N> or <zoom,X,Y>: applies an extent to following -d or -D options
        -f<building>,<street>,<city>{,<postcode>}: finds addresses
        -i: uses imperial units (miles, yards, acres) instead of metric units (kilometres, metres, hectares)
        -n: no info (for use with -d, etc.) does not list global information, tables or layers
        -v: verbose: lists layers
        -V: more verbose: lists layers and low-res layers

Major standard style sheet changes

These changes affect the standard style sheet, style/standard.ctstyle. Users are free to use the standard style sheet in part or in whole, or use their own custom style sheets.

Cities and towns now have icons in the form of five-pointed stars at small scales. The icon for a capital city is a five-pointed star in a circle.

Routes are now drawn at large scales using a smooth envelope without the former kinks and overlaps, and at very large scales arrows are drawn in the direction of travel.

Country borders are drawn using as an inset semi-transparent colour, using a different colour for adjacent countries, when Natural Earth data is used containing the _MAPCOLOR7 attribute.

Major roads are no longer loaded at scales smaller than 1:15 million.

Style sheet XML schema changes

The <repeatedSymbol>, <oneWayArrow>, <startSymbol> or <endSymbol> element can now have a 'color' attribute. The specified color, if the attribute is present, is used to colorize any SVG icon used as a repeated symbol.

Polygon borders can be offset using the 'borderOffset' attribute in the <shape> element, which takes a dimension. To offset the border so that it is precisely inset in the polygon, use 'inset="yes"'.

The <icon> element has a new optional attribute, 'needsLabel'. If 'needsLabel' is 'true' or 'yes' the icon is drawn only if the label is present and can be drawn without overlap.

makemap standard import rules changes

Note that you can examine the standard import rules using the command 'makemap -writerules'.

When importing OSM data, the 'short_name' is now imported into all objects.

If the file land_polygons.shp (the standard file used for coastlines in combination with OSM data) is imported, all objects are now written to the 'outline' layer.

Most Natural Earth data files now have standard import rules, allowing Natural Earth data to be used easily and consistently.

Changes common to all APIs

Added a Framework function to insert elliptical map objects. The C++ function is

Result Framework::InsertEllipseMapObject(uint32_t aMapHandle,const String& aLayerName,
double aCenterX,double aCenterY,CoordType aCenterCoordType,double aRadiusX,double aRadiusY,CoordType aRadiusCoordType,double aRotationDegrees,
const String& aStringAttributes,FeatureInfo aFeatureInfo,uint64_t& aId,bool aReplace);

and other platform APIs are very similar except for iOS, where extra radiusX and radiusY properties have been added to the CartoTypeMapObjectParam class.

Added a function to return points along a great circle between to points given in degrees longitude and latitude. The C++ function is

std::vector<PointFP> GreatCircleLine(const PointFP& aStartPoint,const PointFP& aEndPoint,double aDistanceInMetres)

The NearestRoadInfo class, used by FindNearestRoad to return information, has a new member, SideOfRoad, which supplies
the side of the road on which the selected point lies, or SideOfRoad::None if the vehicle heading is not supplied.
It is Left if the heading vector is left of a vector from the chosen point to the nearest point on the road, otherwise Right.
Another way to understand it is: if the road as seen by the driver of the vehicle is to the left, the side of the road is Right, and vice versa.

Specific C++ API changes

There is a new function to create a MapRenderer object, trapping any errors so that they can be reported. In particular this allows desktop apps like the CartoType Maps App to attempt to load a large number of maps without crashing when there are no more file handles available. The new function is:

static std::unique_ptr<MapRenderer> New(Result& aError,Framework& aFramework,const void* aNativeWindow = nullptr);

specific .NET API changes


Specific UWP API changes


Specific Android API changes

Added the missing Legend methods setMainStyleSheet(), setLabelWrapWidth(), setDiagramColor(), setPolygonRotation(), hasTurnInstruction(),
setTurnInstruction(), and turnInstruction().

Specific iOS API changes

Added the CartoTypeMapObjectParam properties radiusX, radiusY and rotationDegrees to support the insertion of elliptical map objects.

Added the missing Legend functions setMainStyleSheet, setLabelWrapWidth, setDiagramColor, setPolygonRotation, hasTurnInstruction,
setTurnInstruction, and turnInstruction.

This release was made on 9th December 2022 and is based on commit 8.2-57-g51a9fa561 in the new Git repository.

The previous release was made on 5th July 2022 and was based on CartoType-mainline revision 10787 in the Mercurial repository.

Fast street address searching

The makemap tool now creates a street index table. Street address searching is now faster and more accurate when using map files containing the new table. Fast street address searching is used automatically for searches with a street name, a city name or postal code,and an optional building name or number. Abbreviations, omitted words and fuzzy matching are supported.

Mutual accessibility checking for the time/distance matrix function

The TimeAndDistanceMatrix function can run slowly if not all the points supplied are connected together by the network of routable roads. A new Framework function, MutuallyAccessible, checks at high speed whether any group of points is mutually connected, and optionally returns the IDs of the connectivity groups to which the points belong; group 1 is the largest group, so in practice any point not belonging to group 1 is inaccessible. A group ID of zero means that a point is not connected to any other points.

The MutuallyAccessible function is implemented only for the turn-expanded router (/route=t).

Changes common to all APIs

Added function Description (Framework::Description, Util.Description, etc.) to return the Git description of the current version, for example 8.2-55-gb3dc270af.

Added new FeatureType values AdminArea1 ... AdminArea10, Address, PostCode, Position and Quarter.

Replaced Framework function RouteAccess by MutuallyAccessible, which is more useful, and removed the RouteAccess class.

Added experimental functionality to set and get label redraw speed and fix label positions during panning. This functionality consists of Framework functions or properties for label FPS (frames per second) and to enable fixed labels.

Removed Framework function UseSerializedNavigationData; navigation data is now always read in serialized form.

Added function or property LabelUpAngle.

Specific C++ API CHANGES

Added function Rect::Expanded to expand a rectangle by a certain size.

Added functions CartoType::FeatureTypeIsCity and CartoType::FeatureTypeIsPOI.

Removed function Framework::MapUnitSize because map units are now always 32nds of a meter, as defined by the new constant KMapUnitsPerMeter.

Replaced function Framework::SetPerspective(const PerspectiveParam& aParam) with SetPerspectiveParam(const PerspectiveParam& aParam), which no longer turns perspective mode on.

Simplified semantics of function Framework::InsertCopyOfMapObject: string attributes, if supplied, override the original string attributes rather than being added to them.

Changed function Framework::SetLabelUpAngle to return the previous setting.

Removed function TextMetrics::Clear.Added a constant MapTableType::KStreetIndexTable for the new street index.

Removed the point-scale argument from the Route constructor: map units are now always 32nds of a meter.

Removed the PointScale data member from the Route class.

The AbbreviationDictionary class now supports stop words (words which can be removed completely) and suffixes.

The function MString::Abbreviate now takes an optional argument allowing the deletion of stop words.

Added function MString::FuzzyCompare, which returns an integer (0 for equality).

Specific .NET API changes

Removed Get prefix from Util functions 

Specific UWP API changes


Specific Android API changes


Specific iOS API changes



This release was made on 5th July 2022 and is based on mainline revision 10787.

The previous release, 7.8, was made on 28th March 2022 and was based on mainline revision 10409.

This is a major release which introduces many source code incompatibilities. They fall into two categories: renaming of public identifiers, and the introduction of simpler and consistent feature types for map objects. The aim is to make CartoType applications easier to write, read and debug.

The previous release will continue to be supported until 31st July 2024 and will receive bug fixes but no new features.


Classes, functions and other identifiers have been systematically renamed, with the aim of improving consistency and removing outdated and unnecessary conventions.

Renaming in the C++ API

The general principle for the C++ API is to use Pascal case (the first letter of each compound word in an identifier is capitalised).

For reasons of supporting .NET APIs, the main namespace is now named CartoTypeCore. However, the name CartoType is defined as an alias if the header cartotype.h is used. Therefore user applications can continue to use the CartoType namespace qualifier.

Classes no longer have C (class) and T (type) prefixes. The M (mixin or interface) prefix, as in MString, has been retained. In most cases the removal of the prefix is quite simple, but in a very few cases such as TContour and CContour, which have become ContourView and Contour, and TBitmap and CBitmap, which have become BitmapView and Bitmap, other changes were necessary to avoid ambiguity.

Public data members no longer have the i (instance) prefix. For example, the Point class has data members X and Y. The former TPoint class had data members iX and iY.

The Rect and RectFP classes now have Min and Max data members, not TopLeft and BottomRight.

The Get prefix has been removed where possible: that is, from functions which return a single value that is implied by their names.

The K prefix has been retained for public numeric constants.

Renaming in the .NET API

The general principle for the .NET API is to use Pascal case.

Public data members now use Pascal case instead of the former convention of prefixing with m_. Where possible, these public data members have become properties. For example, the public data member RouteProfile.m_vehicle_type has become the property RouteProfile.VehicleType.

As with the C++ API the Get prefix has been removed where possible. For example, the function Geometry.GetCoordType has become the property Geometry.CoordType.

The K prefix has been retained for public numeric constants.

Renaming in the Android API

The general principle for the Android API is to use Pascal case for classes, and camel case (the first letter is lower case and other words in a compound identifier are capitalised) for public methods and public data members.

The i prefix has been removed from public data members. For example, LocationMatchParam.iLocationAccuracyInMeters has become locationAccuracyInMeters.

The get prefix has been removed where possible. For example, Framework.getLastMapHandle has become Framework.lastMapHandle.

Renaming in the iOS API

The general principle for the iOS API is to use Pascal case for classes, prefixed by CartoType to avoid ambiguity, and camel case (the first letter is lower case and other words in a compound identifier are capitalised) for public methods and public data members.

This has resulted in relatively little renaming. One example is the change of the CartoTypeRect public data members from x_min, y_min, x_max, and y_max to minX, minY, maxX and MaxY.

The get prefix has been removed where possible, and in many cases getters and setters have been replaced by properties.For example, the methods CartoTypeFramework.setNightModeColor and CartoTypeFramework.getNightModeColor have been replaced by the property CartoTypeFramework.nightModeColor.

The FeatureInfo class: consistent map object properties

The former integer attribute of a map object has been replaced by a FeatureInfo object. There is no size or efficiency overhead because FeatureInfo wraps a 32-bit integer.

Formerly the meaning of a map object's integer attribute was determined by convention, and without knowing those conventions it was impossible to discover the road type (e.g., Primary Road) or non-road feature type (e.g., Fuel Station) of a map object, or the access restrictions, level, one-way status, etc., of an object.

A FeatureInfo object has as one of its attributes a FeatureType. The FeatureType enumerated class combines the former TRoadType, OsmAttrib, and TPointOfInterestType types (to use the C++ names).

The main effect on the CartoType API of the FeatureInfo class is that a FeatureInfo object now needs to be supplied where formerly an integer attribute value was used, as in the functions to insert map objects.

The feature info for a route object contains:

  • discriminator: ordinary route, bridge or tunnel
  • a level in the range -8...+7
  • a feature type in the range 0...31; these are the route types, which also act as indexes into speed and bonus arrays in route profiles
  • flags for one-way, drive-on-left, roundabout and toll road
  • speed limit in kph
  • gradient code (only avalable in internal route calculation layers)
  • access flags (wrong-way, pedestrian, cycle, motor, emergency, other)

The feature info for a non-route object contains:

  • discriminator: always 0
  • a level in the range -8...+7
  • a feature type in the range 32...32767
  • a sub-type in the range 0...2047; sub-types are used to distinguish island sizes, settlement ranks, etc.

Simpler style sheets

CartoType 8.0 can read older style sheets correctly, with some very minor exceptions, but some attributes and other usages in style sheets have been simplified or abolished.

  • The roadflags attribute, used in the <CartoTypeStyleSheet> and <layer> elements, is no longer needed.
  • OsmType and RoadType in expressions have been replaced by @feature_type.
  • Type in expressions has been replaced by @sub_type, and it is no longer necessary to use a mask: for example, exp='(Type bitand #FFFF)=4' becomes exp='@sub_type=4'.
  • Attributes of a map object can be tested consistently in style sheet expressions using the variables @ or @type (map object type), @layer, @id, @feature_type, @feature_type_name, @sub_type, @level, @bridge, @tunnel, @one_way, @one_way_forward, @one_way_backward, @drive_on_left, @drive_on_right, @roundabout, @toll, @gradient, @private, @pedestrian_access, @cycle_access, @motor_vehicle_access, @other_access, and @wrong_way.

A new CTM1 format: CTM1 8.0

In the new CTM1 format, 8.0, FeatureInfo values are used consistently where either TRoadType, OsmType or KArc... values were used. The new version of makemap always creates CTM1 8.0 files. If you need to create CTM1 files in older versions (4.2 to 7.1) you can use the older version of makemap, now renamed makemap7.

Versions of CartoType before 8.0 cannot read CTM1 8.0 files.

CartoType 8.0 can read all CTM1 file formats from 4.2 to 8.0 inclusive.

New import rules

Many of the import rule commands have changed to support the new feature info system.

  • set_osm_type and set_road_type have been merged into set_feature_type; for example, <set_osm_type name='bou'/> becomes <set_feature_type name='bou'/>, and <set_road_type name='Motorway'/> becomes <set_feature_type name='motorway'/>.
  • set_road has been replaced by specific attribute setters such as set_cycle_access, set_pedestrian_access, etc.; set_feature_info_raw_value is available where low-level access is needed.
  • set_int_low has become set_sub_type.

The new version of makemap cannot read old-style import rule files (.makemap files) correctly. If you need to create CTM1 files using old-style .makemap files you can use the older version of makemap, now renamed makemap7.

This release was made on 29th March 2022 and is based on mainline revision 10409.

The previous release, 7.6, was made on 18th October 2021 and was based on mainline revision 10121.

Added time/distance matrix function

There is now a function to return a time/distance matrix giving the route time and distance for all combinations of a set of start points and a set of end points. It is implemented for the turn-expanded contraction hierarchy  /route=tech), turn-expanded (/route=t), and a-star (/route=a) routers. The fastest implementation by far is that for the TECH router, but that implementation does not support arbitrary run-time route profiles or dynamic road closures. The fastest flexible implementation, which does support those features, is that for the turn-expanded router.

There is a new makemap option, /hublabels=yes, which can be used in conjunction with /route=tech to add hub label data to the TECH route data to enable ultra-fast calculation of time/distance matrices.

Added route access function

There is now a function to return the accessibility of a point for routing purposes. It is implemented for the turn-expanded router (/route=t) only.

Added a function to get the traffic info speed limit

There is now a function to get the speed limit if any imposed by dynamic traffic information for a point. It returns the traffic info speed limit in kph for a given point and given vehicle types; that is, the most severe restriction applying to that point for polygonal restrictions containing the point, and for the nearest road to the point.

More consistent style sheet icons

Some standard style sheet icons have been changed for a more consistent appearance.

UWP support

CartoType is now available as a Universal Windows Platform (UWP) component. The API is very similar to the .NET API, but not identical because in UWP function overloading on anything other than number of arguments is not allowed.

C++ API changes

CFramework::EnableMapByHandle now returns TResult, not void
CFramework::EnableAllMaps now returns TResult, not void
Added CFramework::TimeAndDistanceMatrix
Added CFramework::RouteAccess
Removed CFramework::ObjectsDrawn
CFramework::GetMapGraphicsContext now returns std::shared_ptr<CGraphicsContext>, not CGraphicsContext&
The CFramework functions void AddNavigatorObserver(std::weak_ptr<MNavigatorObserver> aObserver) and
RemoveNavigatorObserver(std::weak_ptr<MNavigatorObserver> aObserver) have been replaced by
AddObserver(std::weak_ptr<MFrameworkObserver> aObserver) and
RemoveObserver(std::weak_ptr<MFrameworkObserver> aObserver)
Added CFramework::GetTrafficInfoSpeed
Removed the unused parameter aLabelMaxLength from CFramework::LoadIcon
The TFont class is now safer: it stores smart pointers to the engine, typeface and alt typeface, not raw pointers
Removed unused data members iWeight, iWorks, iToll and iLanes from CTrafficInfo
Added the CTimeAndDistanceMatrix class. An object of this type is returned by CFramework::TimeAndDistanceMatrix
Added the TRouteAccess enumeration. A value of this type is returned by CFramework::RouteAccess
Added the TAbbreviationType enumeration to specify where in a phrase an abbreviation can be used
Added the CAbbreviationDictionary type mapping a string to a TAbbreviation
MString::Abbreviate now takes a CAbbreviationDictionary instead of a CStringDictionary
Added a TText constructor taking null-terminated UTF-16 text
Added the TAbbreviation and TAbbreviationTableEntry classes to support the new abbreviation system

.NET API changes

Added PointValue: a value type for 2D points with floating-point coordinates
Added the TimeAndDistanceMatrix class
Added the RouteAccess enumeration
Added Framework.GetTimeAndDistanceMatrix
Added Framework.GetRouteAccess
Removed the unused parameter aLabelMaxLength from Framework.LoadIcon

Android API changes

Added Framework.timeAndDistanceMatrix
Added Framework.routeAccess
Added the TimeAndDistanceMatrix class
Added the RouteAccess class
Renamed Geometry.IntersectionType to intersectionType for consistency,
and renamed all other Geometry public functions starting with
capital letters to start with small letters in the same way
Removed unused data members iWeight, iWorks, iToll and iLanes from TrafficInfo

iOS API changes

Added the timeAndDistanceMatrix function to CartoTypeFramework
Added the routeAccess function to CartoTypeFramework
Added the CartoTypeTimeAndDistanceMatrix class
Added the CartoTypeRouteAccess enumeration
Added the CartoTypePointSet class for use by the timeAndDistanceMatrix function
Removed unused data members weight, works, toll and lanes from CartoTypeTrafficInfo

This release was made on 18th October 2021 and is based on mainline revision 10121.

The previous release, 7.4, was made on 27th July 2021 and was based on mainline revision 9961.

A new routing system with compact data

There is a new routing system, Turn-Expanded Compact. Use the option /route=tc in makemap. It requires much less run-time memory, but, unlike the contraction hierarchy systems, allows arbitrary route profiles to be set at run time. It is suitable for large areas such as the whole of the UK on mobile platforms like iOS and Android.

Map file metadata

There are new framework functions called MapMetaData, getMapMetaData, etc., in all APIs, to retrieve metadata from loaded maps. To get metadata for the first CTM1 file, call MapMetaData(0). The information returned includes the version of CartoType used to build the map, the type of route data it contains, its extent in degrees, and the projection name and parameters. The Maps App now displays metadata in its About dialog.

Labelling improvements (already merged into 7.4)

  • Fixed case 5909: not all labels are displayed in graphics accelerated mode.
  • Many more islands and polygons are now labelled.
  • Sea areas (bays and straits) are now imported and labelled.
  • Icons without labels are now displayed if the label position in the style sheet is 'icon'.

Improvements to tiled routing

Tiled routing now works even if an individual tile may be greater than 4Gb in size. If you get an error message like
'file position 0x1003be20b is too big to be stored in 4 bytes; try again using /largefile=yes', you can now act on the error
message and makemap will create both the main map and the tiles with 5-byte file positions.

Changes during the lifetime of 7.6

--- 7.6.0 ---
fixed case 5948: z-level adjustment not working for tiled NavStreets data
fixed case 5949: set_roundabout sets the one-way flag in XML input scripts (.makemap files) but not in ChaiScript; it no longer sets the one-way flag
implemented case 1361: pushpins that combine into one
--- 7.6.22 ---
fixed case 5953: crash in TileBitmap; parsing error in a style sheet caused write to a null pointer when assembling the error code
fixed case 5956: SetStyleSheet should parse style sheet at all zoom levels before installing it
fixed case 5957: segment fault when loading TIFF file; added default projection (Web Mercator) for images lacking a PRJ file or projection information in a TIFF table and new makemap command-line option /imageprojection=<EPSG code>
implemented case 5959: show parking icon only where parking is public; private car parks are no longer imported
implemented case 5960: suppress all duplicate strings in labels so that buildings and cities are not named twice
--- 7.6.30 ---
fixed case 5961: setting night mode does not work properly with the tile server
text drawing failed when a box formatting character (a Unicode private use character) was encountered
fixed case 5931: island label is duplicated
speeded up address finding by restricting the layers searched for nearby and surrounding items
CMapObject::VerboseDescription now reports the driving side
MPath::OffsetPath no longer smooths the offset path because parts of routes where the path goes back on itself disappear
fixed case 5964: extra turns around waypoints with CH routing
--- 7.6.39 ---
fixed regression: the Linux SDK no longer built the Qt map rendering library
fixed case 5965: two 15 weight turns at intersection to avoid one 20 weight traffic light turn for the turn-expanded router; turn delays should have been imposed even at junctions with no choice
fixed case 5964: extra turns around waypoints, for the other routing systems
fixed failure to create correct route data or use it correctly if route data was larger than 4Gb
--- 7.6.50 ---
CNavigator::Range did not restore the routing profile after changing it
the TECH routing data was written with many duplicate shortcut arcs; the new version of makemap writes TECH data that is half the size
--- 7.6.55 ---
fixed case 5969: horizontal bands flipped vertically in TIFF file
code to remove heading vector segment was wrong in turn expanded router
insertMapObject in the Android API was mistakenly private, not public
the turn-expanded router set the position in lat/long for backward roads incorrectly
retargeted the C# demo to use .NET 4.8 because earlier versions are no longer supported or will soon reach end of life
changed the Windows and .Net build scripts to use vs2022
an arc connected at both ends to the same node caused a crash in makemap when creating CH data for Latvia
--- 7.6.66 ---
CGeometry objects containing off-curve points were not converted into COutline objects correctly: the off-curve points were converted to on-curve points
setting traffic info now uses the current route profile, not a default car profile
fixed a possible crash in the tc router when adding traffic restrictions
fixes case 5978: polygon traffic restrictions defined by roads do not work in the A-star router
FindAddress did not obey the aMaxObjectCount argument
printing didn't work in the Windows maps app because the Windows printer support DLL wasn't distributed with the app
--- 7.6.73 ---
the turn-expanded router did not create turn information correctly at the start and end of routes
the delay-at-junction flag was not serialised in the turn-expanded router data
turn-expanded compact data now uses less RAM when being read, making it more likely for low-memory platforms to be able to load map data
fixed case 5984: shortest route option doesn't work
--- 7.6.81 ---


This release was made on 27th July 2021 and is based on mainline revision 9961.

The previous release, 7.2, was made on 13th May 2021 and was based on mainline revision 9870.

Setting colors of map objects individually

It is now possible to give every map object that is a line or a polygon its own main color and border color, overriding any colors set in the style sheet. Formerly that was possible only for
icons. The new feature is principally useful when inserting map objects at run time ('dynamic map objects') but can be used when building the CTM1 file by inserting appropriate logic in the .makemap rules.

The colors are set using the map object attributes _color and _border_color. They can use any color expression that is valid in a style sheet. For example: 'blue', 'orange+0.25white', '#A00', '#08123456'. Formally, a color expression consists of one or more sections separated by plus signs. The format of a section is

{ '+' { blend-ratio } } hex-color | color-name

where blend-ratio is an optional number; if it's between 0 and 1 inclusive it's treated as a fraction, otherwise as a number of 255ths; and hex-color is either #RGB, #RGBA, #RRGGBB or #RRGGBBAA. The plus sign and blend-ratio are legal only if there is a previous color to blend with.

Applying color effects to the entire style sheet: generalising night mode

Previous versions allowed a 'night mode' to be set, in which roads were made brighter and other layers were blended with a dark color to make them less prominent.

It is now possible to apply color changes to any layer or layers in the style sheet using a blend style set (TBlendStyleSet in the C++ API), which is a vector of blend styles. A blend style is a list of style names, which may include names with wild cards, and a series of colors to be blended with the main color, border color, text color, text glow color, and icon color for those styles. The blend styles are applied in order.

This generalisation of the idea of night mode allows, for example, all map objects to be drawn in a faint version of their usual colors, by blending with white, except for layers of interest, which can be drawn in brighter colors.

The colors in a blend style are treated as RGB colors. The alpha value is used as the blend ratio. The alpha value of the target color is preserved during blending, to maintain the overall visual intent of the style sheet.

New error codes to diagnose missing files and style sheet errors

There are three new error codes, KErrorMapNotFound (63), KErrorFontNotFound (64) and KErrorStyleSheetNotFound (65) to help identify the reason for a failure to create a Framework object.

In addition, style sheet errors can be located by line and column number. The error codes returned by XML parsing have been redesigned to hold the Expat parser error code, the line number, and the column number of the error. XML errors are now in the range KErrorXmlRangeStart (0x10000000) to  ErrorXmlRangeEnd (0x2AFFFFFF) inclusive. The high byte is 0x10 for errors specific to CartoType's style sheet system (e.g., nested <layer> sections), or is in the range 0x11 to 0x2A for Expat XML parser error codes. The low three bytes give the error location: one byte for the column number and the two low bytes for the line number.

The ErrorString function, which now exists on all platforms, unpacks this and other error codes into a readable string, which is supplied when an exception is thrown on the .NET, Android and iOS SDKs. In the C++ SDK the exception type remains TResult, but the user can easily call ErrorString to obtain the string version of the error.

Inserted objects are drawn in order of insertion

Map objects inserted at run-time are now drawn, if they are in the same layer and the same <condition> within the layer, in order of their map object IDs, which by default is the order in which they are inserted. Thus newer objects are consistently drawn over older objects so that user supplied graphics can be used to build up a picture.

This release was made on 5th March 2021 and is based on mainline revision 9722. It is a major release with incompatible changes to APIs, which are detailed below.

The previous release, 6.2, was made on 5th September 2020 and was based on mainline revision 9241.

Tiled route data

The makemap tool can now split contraction hierarchy route data into tiles. Any subset of the tiled maps from a particular makemap run can be used together, and routing will work using the tiles that are present. You can load and unload maps at any time. Routing will use the tiles that are available. If you load extra tiles and recreate a route, the new route may be different because of the added route data. If CartoType can't create a route because of missing tiles you will get the 'no route connectivity' error.

To create a set of tiled maps, use the makemap option /route=ct{N} for ordinary contraction hierarchy (the same system as /route=cs), or /route=tt for turn-expanded contraction hierarchy (the same system as /route=tech). The optional value N is the tile size in degrees, the default value being 1. Legal values are 1, 2, 4, 8 and 16. 4 is recommended for most purposes.

Removal of home-grown integer types

The integer types CartoType::int32, CartoType::uint16, etc., have been removed from the C++ API because they are no longer needed. The standard integer types int32_t, uint16_t are used instead.

Internal use of exception-based error handling

Nearly all internal functions now use exceptions of type TResult instead of error codes. This does not affect the public APIs, which still use error codes. The move to exceptions makes the code more reliable, less prone to memory leaks, and easier to maintain and debug. The error codes KErrorOverlap, KErrorPathLengthExceeded, KErrorMaxTurnExceeded, and KErrorCentralPath are no longer used, and a new error code KErrorXmlFeatureNotSupported (value = 62) has been added. No existing error codes have changed.

Removal of obsolete features

  • The ability to draw maps from a tile source has been removed.
  • The image server, which was a system to draw maps using cached tile bitmaps, has been removed.
  • Support for the web map service (WMS) system has been removed.

C++ API changes

  • CBitmap has a new constructor: explicit CBitmap(MInputStream& aInputStream)
  • The result constants KErrorNone, etc., now have type TResult, not int32_t, so that when they are thrown as exceptions the type is distinct.
  • The result constants KErrorOverlap, KErrorPathLengthExceeded, KErrorMaxTurnExceeded, KErrorCentralPath, have been removed.
  • Graphics operations now return TDrawResult, not TResult.
  • CFrameworkEngine::CancelDrawing has been removed.
  • TViewState has a new constructor: explicit TViewState(const char* aXmlText)
  • The CFramework::AppendStyleSheet functions now return TResult instead of being void.
  • A new function 'TFileLocation StyleSheetErrorLocation() const' returns error location information set by the last style sheet load operation.
  • CFramework::GetHeights now returns a vector of integers instead of writing to pointers supplied by the caller.
  • CFramework::SetNearbyObjectWarning now takes an extra parameter, a reference to TResult.
  • CFramework::SetVehicleTypeWarning now takes an extra parameter, a reference to TResult.
  • CFramework::SetVehiclePosOffset is now void instead of returning TResult.
  • There is a new function 'bool CFramework::TrackIsDisplayed'.
  • The deprecated overload of CFramework::InsertMapObject taking an object type has been removed.
  • The obsolete CFindFramework class has been removed.
  • Clipping and envelope functions have been added to CGeometry, allowing geometry objects to be built from operations on map objects.

The following functions now return TResult instead of being void:

  • CFramework::License
  • CFramework::SetTurnInstructions
  • CFramework::Resize
  • CFramework::SetScaleDenominator
  • CFramework::SetScaleDenominatorInView
  • CFramework::Zoom
  • CFramework::Rotate
  • CFramework::SetRotation
  • CFramework::SetViewLimits
  • CFramework::SetMainProfile
  • CFramework::AddProfile
  • CFramework::GetNavigationData
  • CFramework::DisplayTrack

.NET API changes

  • Clipping and envelope functions have been added to Geometry, allowing geometry objects to be built from operations on map objects. They use the new ClipOperation enum class.
  • There is a new GeometryList class which is a list of Geometry objects.
  • The function Framework.SetCase has been added to provide letter-case operations in a consistent way. It uses the new LetterCase enum class.

The following functions now return Result instead of being void:

  • Framework.License
  • Framework.SetTurnInstructions
  • Framework.SetScaleDenominator
  • Framework.SetScaleDenominatorInView
  • Framework.Zoom
  • Framework.Rotate
  • Framework.SetRotation
  • Framework.SetMainProfile
  • Framework.AddProfile

Android API changes

  • Clipping and envelope functions have been added to Geometry, allowing geometry objects to be built from operations on map objects. They use the new ClipOperation enum class.
  • The deprecated functions Framework.version, and Framework.setAttribute have been removed. Use Util.version, and Util.setAttribute instead.
  • The deprecated version of Framework.insertMapObject that took a map object type parameter has been removed. Use the new version which
    deduces the map object type from the gemoetry object passed in.
  • The function Framework.getPolygonArea has been removed. Use the new function getArea, which takes a Geometry object. There is also
    a new function GetLengthOrPerimeter which takes a Geometry object.
  • The deprecated route creation functions taking coordinate arrays have been removed. Use the versions taking a RouteCoordSet object.
  • The function Framework.profile has been added to return one of the currently active route profiles.
  • The function Framework.getHeightProfile has been removed.
  • The function Framework.useImageServer has been removed because the image server system is no longer supported.
  • There is a new function Framework.setCase to set the letter case of a string. It uses the new LetterCase enum class.

The following functions now return an integer error code instead of being void:

  • Framework.license
  • Framework.setTurnInstructions
  • Framework.resize
  • Framework.setScale
  • Framework.setScaleDenominatorInView
  • Framework.zoom
  • Framework.zoomIn
  • Framework.zoomOut
  • Framework.rotate
  • Framework.setRotation
  • Framework.setRotationAt
  • Framework.setMainProfile
  • Framework.addProfile

iOS API changes

All methods taking 'const char *' in the Objective C interface now take 'NSString*'.

Structures called CartoTypePointAndResult, CartoTypeIdAndResult, and CartoTypeAreaLengthAndResult have been added to make it possible
to return multiple results without using unsafe pointers.

  • The CartoTypeCoordSet struct has been removed.
  • The CartoTypePath protocol's point method now returns a CartoTypePathPoint directly instead of taking a pointer to CartoTypePathPoint.
  • CartoTypeMapObject now implements the CartoTypePath protocol.
  • Clipping and envelope functions have been added to CartoTypeGeometry, allowing geometry objects to be built from operations on map objects. They use a new enum, CartoTypeClipOperation.
  • There is a new method in CartoTypeFramework called setCase to set the letter case of a string. It uses the new CartoTypeLetterCase enum.
  • The CartoTypeFramework method loadMapWithTileParam has been removed because tiled map data sources are no longer supported.
  • The CartoTypeFramework methods insertPushPin and insertCopyOfMapObject now return CartoTypeIdAndResult so as to return the new object's ID without having to use an unsafe pointer.
  • The CartoTypeFramework method deleteObjectsFromMap now returns the number of objects deleted, not a CTResult.
  • The CartoTypeFramework method convertCoords now takes a CartoTypeGeometry object instead of a CartoTypeCoordSet.
  • The CartoTypeFramework method convertPoint now returns CartoTypePointAndResult so as to return the converted point without having to use an unsafe pointer.
  • The CartoTypeFramework method getHeights now takes a CartoTypeGeometry and returns an array of NSNumber.
  • The CartoTypeFramework method getHeightProfile has been removed.
  • The deprecated route creation methods taking CartoTypeCoordSet have been removed. Use the versions taking a CartoTypeRouteCoordSet object.
  • The CartoTypeFramework method getProfile has been added to return one of the currently active route profiles.
  • The CartoTypeFramework method getBuiltInProfile now returns a CartoTypeRouteProfile object instead of a CTResult.

The following CartoTypeFramework methods now return CTResult instead of being void:

  • license
  • setTurnInstructions
  • setMapWidth:andHeight
  • setScaleDenominator
  • setScaleDenominatorInView
  • zoom
  • rotate
  • setRotation
  • setMainProfile
  • setMainProfileType
  • addProfile



This release was made on 13th May 2021 and is based on mainline revision 9870.

The previous release, 7.0, was made on 5th March 2021 and was based on mainline revision 9722.

Map object editing functions

There are new functions to make it easier to add interactive editing to a CartoType application. They manage the creation and editing of linear and polygonal objects by means of pointer presses and movements and allow the new objects to be added to any layer of the map.

The Maps App demonstrates some of the new functions using these actions:

  • Double-click starts a new linear object OR select an existing object; when selecting an object the action selects an existing point if near enough, otherwise creates a new point.
  • Shift-double-click starts a new polygonal object OR selects an existing object if near enough in the same way as plain double-click.
  • Escape terminates editing the current object.
  • Backspace deletes the last point if there are more than two (for a line) or more than three (for a polygon). It then terminates editing the current object.
  • Delete removes the current object, asking for confirmation first.

During editing, the length or area of the current object is shown in the status bar at the bottom of the window.

The map editing functions are as follows in the C++ API. They have similar names in the other APIs.

Sets the map used to store editable objects. Does not affect objects already created.
If this function is not called, editable objects are stored in the map used for
route objects.
TResult CFramework::EditSetWritableMap(uint32_t aMapHandle);
 /** Creates a new editable line object starting at the specified point. */
TResult CFramework::EditNewLineObject(const TPointFP& aDisplayPoint);

/** Creates a new editable polygon object starting at the specified point. */
TResult CFramework::EditNewPolygonObject(const TPointFP& aDisplayPoint);

/** Moves the editable object's current point if any. */
TResult CFramework::EditMoveCurrentPoint(const TPointFP& aDisplayPoint);

/** Adds a new point to the editable object by copying the current point. */
TResult CFramework::EditAddCurrentPoint();
 /** Deletes the editable object's current point unless that would result in a line object of fewer than 2 points, or a polygon object of fewer than 3. */
TResult CFramework::EditDeleteCurrentPoint();

/** Deletes the current editable object. */
TResult CFramework::EditDeleteCurrentObject();

Selects an editable object by selecting the nearest point of any editable object within a given radius.
If the point is not within the given radius of an existing point, creates a new point.
TResult CFramework::EditSelectNearestPoint(const TPointFP& aDisplayPoint,double aRadiusInMillimeters);
Inserts the currently edited object into a chosen layer, converting it from an edited object into an ordinary object.
If aId is non-zero and aReplace is true, replaces any existing object with that ID, otherwise creates a new object.
The ID of the new object is returned in aId.
TResult CFramework::EditInsertCurrentObject(const CString& aLayer,uint64_t& aId,bool aReplace);
 /** Sets a string attribute in the currently edited object. If aKey is empty, sets the label. If aValue is empty, deletes the attribute. */
TResult CFramework::EditSetCurrentObjectStringAttribute(const CString& aKey,const CString& aValue);

/** Sets the integer attribute of the currently edited object. */
TResult CFramework::EditSetCurrentObjectIntAttribute(uint32_t aValue);

Returns the area and length of the currently edited object.
For line objects returns 0 and the length in meters.
For polygon objects returns the area in square meters and the perimeter in meters.
TResult CFramework::EditGetCurrentObjectAreaAndLength(double& aArea,double& aLength) const;

Saving and loading maps to and from memory

There are new functions to save maps to memory and load them from data stored in memory. They are intended to allow applications to save small numbers of user-added objects, such as pushpins and objects added using the new editing functions, to serialised strings that can be stored in an application data system such as UserDefaults on iOS.

The new functions are as follows in the C++ API. They have similar names in the other APIs.

Saves selected objects to a map identified by its handle by writing them as an array of bytes in CTMS format.
aFindParam can be used to select the objects to be saved.
If aMapHandle is zero it means the in-memory map used for routing.
TResult CFramework::SaveMap(uint32_t aHandle,std::vector<uint8_t>& aData,const TFindParam& aFindParam);
Reads map data from aData in CTMS format and merges it into the map identified by aHandle,
which must refer to a writable map database.
If aMapHandle is zero it means the in-memory map used for routing.
TResult CFramework::ReadMap(uint32_t aHandle,const std::vector<uint8_t>& aData)

Map object convenience functions returning points in lat/long

There are new convenience functions in CMapObject or MapObject to return points in degrees of latitude and longitude.

The new functions are as follows in the C++ API. They have similar names in the other APIs.

Returns the center of a map object in degrees.
The center is defined as the center of gravity for polygons and arrays,
a point half way along the path for lines, and the point itself for points.
Because the center is calculated using map coordinates then converted to degrees,
it depends on the map projection used by the map object.
TPointFP CMapObject::CenterInDegrees(TResult& aError) const;
 /** Returns the bounding box of a map object in degrees. */
TRectFP CMapObject::BoundsInDegrees(TResult& aError) const;
 /** Returns the geometry of a map object in degrees. */
CGeometry CMapObject::GeometryInDegrees(TResult& aError) const;

Finding the route taking the shortest time

The normal function of the 'shortest' flag in the route profile object (iShortest in C++) is to make routing provide the shortest route by distance. It is now possible to change that behaviour so that the shortest route by time, not distance, is found. To do that, set the new flag iShortestByTime to true It has an effect only when iShortest is also set; that is, it modifies the behaviour of iShortest.

Enable and disable hardware-accelerated drawing by a separate thread (Windows and .NET only)

A function has been added to enable and disable hardware-accelerated drawing by a separate thread:

Enables or disables drawing by a separate thread. Returns the previous state.
This function is intended for users who need the full capacity of the GPU
for a period when drawing is unnecessary.
When drawing is disabled, draw events can be handled by calls to Draw, but it is also necessary
to create a timer to redraw occasionally (e.g., once per second) to allow missing tiles to be
created and drawn after pans, zooms and other changes affecting the display.
bool CMapRenderer::Enable(bool aEnable);

iOS-only changes

In anticipation of Apple removing support for GLKit, which provides an OpenGL ES 2.0 API, CartoType's iOS SDK now uses the open-source MetalANGLE framework instead of GLKit.

The iOS SDK is now supplied as a zip file, not a DMG file. It contains SDKs for both iOS on a device and iOS on a simulator. Note that when you create an app using this new SDK you have to add both the iOS and the MetalANGLE SDKs to your app. Select your app, then select your build under TARGETS, then Build Phases -> Embed Frameworks, then add both CartoType.framework and MetalANGLE.framework, and tick 'Code Sign On Copy'.

Added missing functions:

CartoTypeFramework.getHeight to get the heights above sea level of the points in a Geometry object

.NET-only changes

Removed deprecated functions and other obsolete functions:

MapObject.GetIntegerAttribute(int aIndex)
Framework.InsertMapObject(int aMapHandle,MapObjectType aType,String^ aLayerName,Geometry^ aGeometry,
String^ aStringAttributes,int aIntAttribute,Int64% aId,bool aReplace)

For the last function, use the new version without aType. The type is now deduced from the type of the
geometry object.

Android-only changes

Added missing functions:


Removed obsolete functions:


Release date: 7th February 2018

Previous release: 4.4, 27th July 2017

Summary of changes

The graphics acceleration system known as CartoType GL is now incorporated into the standard version of CartoType. To use it, you create a CFramework object in the normal way, loading the map, style sheet and fonts, then create a CMapRenderer object referencing your framework. You can then draw the map at, for example, thirty frames per second, in response to a timer event.

The CMapRenderer class is a C++ class. For Android there is the Java class MapRenderer, and for iOS there is the Objective C class CartoTypeMapRenderer.

Graphics acceleration is available for iOS, Android, Windows (desktop), OS X (Macintosh), and Linux. It is available on the Qt framework for Windows (desktop), OS X (Macintosh) and Linux.

Evaluation SDKs (software development kits) allow you to try out CartoType before you buy a license. You will be able to create a test application and  find out whether CartoType is the right solution for you. The evaluation SDKs have a few restrictions, including placing a watermark on every map, but provide access to the complete API (application programming interface) and all features including graphics-accelerated rendering.

The CartoType evaluation SDKs (software development kits) are provided for evaluation only, excluding any commercial use. For commercial licensing please contact us.

By clicking on any of the links on this page, or by using the SDK material or demonstration programs, or source code, however acquired, you accept the terms of the CartoType Evaluation License and you also accept that neither CartoType Ltd, nor any owners, shareholders or officers of CartoType Ltd, or any other contributors to, authors of or maintainers of the CartoType system, are liable for any damage, direct or consequential, caused by downloading, installing or using the SDK, or by any programs built using the SDK, and that the SDK is not warranted fit for any particular use and is for evaluation use only and may not be used for any commercial purpose.

To uninstall any of these SDKs, all you need to do is delete the files from your computer.

Sample Maps

To save download time, the SDKs contain only a single sample map. It is of the Isle of Wight, an island off the southern coast of England, chosen because of its good mix of features: urban, rural, and coastal. Please contact us if you need a map of any particular area for evaluation purposes.

Sample Code

The source code for most of our demonstration programs is available in public GitHub repositories in the account code for the current release is here: The code is supplied under the permissive MIT license.

Release notes

The current version of the CartoType SDK is release 8.6. It was released on 8th August 2023.

The current build is 8.6-84-g7efc08bdc, uploaded on 3rd October 2023.

Changes since initial release of 8.6

--- 8.6.17 ---
updated the Android build system to work with the latest Android Studio (Giraffe)
fixed #173: UWP SDK crashes with access violation in in the renderer
fixed #183: range calculation crashes
text index and street index are no longer read if requested text index levels are -1: fixes #156: map of Britain and Ireland takes 9Gb RAM
--- 8.6.31 ---
IMPORTANT: fixed #184: release 8.6 is slower than 8.4
--- 8.6.57 ---
fixed #189: enabling and disabling maps does not work
makemap creates urban areas more accurately; fixes #192
the standard style sheet now draws urban areas after land layers
--- 8.6.66 ---
fixed #83: seabed texture not drawn when graphics acceleration is turned off
improved order of layers in CTM1 files for better search relevance
fixed #195: 3D buildings were not drawn
--- 8.6.71 ---
repeating textures now have their own vertex array: fixes #194
wetland hachure color is now ncsblue
fixed #196: route colours should not be made darker in night mode
English names are now generally drawn on a separate line, using a forced line break, apart from minor and mid-level roads; and English names have now been added for some layers where they were not used.
added CALLBACK macro (_stdcall) needed for WinHttpSetStatusCallback to compile in 32-bit build
updated to the version of the naett library used by the mainline
added a rule for contour shapefiles: *.contours.shp
added a contour layer to the standard style sheet
fixed a typo in standard import rules: height attrib imported from contour shapefiles should be H, not _H
fixed #199: the /split option in makemap did not copy string attributes
removed unneeded function MapObject::Split after fix to #199
fixed #203: Android apps crash on two-finger gesture at edges of display
--- 8.6.84 ---

The Android SDK

The Android SDK allows you to use CartoType with the Android operating system. You use the CartoType Android API, which gives you access to all the features of CartoType: loading maps, adding your own objects to the map, panning, zooming, address searching, routing and navigation.

Download link: Android SDK

The SDK is a ZIP file of about 22Mb. It contains a folder called cartotype_android_sdk_evaluation containing the following folders:

libs: an .AAR (Android archive) called cartotype.aar, which is the CartoType library. Add it to your Android Studio project as a dependency.

font: standard fonts; for simple CartoType use you need load only DejaVuSans.ttf

map: sample maps

style: the standard style sheets; you should load standard.ctstyle with the sample map

doc: licenses and acknowledgments for third-party libraries

Android demo program with source code

CartoTypeMaps is a full-featured sample program for CartoType on Android. It's provided as an Android Studio project, and includes the handling of user gestures for panning, zooming and rotation, routing using different profiles, turn by turn navigation, finding placenames and addresses, night mode, and perspective mode. You can set the start or end of a route using a long press. Other features are available from the menus. CartoTypeMaps is ready to run. Just download the code or use git to clone the repository (git clone Then load the project src/demo/android_demo/CartoTypeMaps into Android Studio, connect an Android device or simulator, and select Run 'app' from the Run menu.

You can also download a prebuilt version: CartoTypeMaps as an APK file (235Mb download). You can install it on your Android phone or tablet. It comes with a map of London and the surrounding area. You can easily load other maps if you prefer.


The iOS SDK allows you to build CartoType apps for the iPhone and iPad. It is supplied as a .dmg file (Apple Disk Image) containing the file CartoType.framework. You use the CartoType iOS API, written in Objective C, which gives you access to all functionality.

Note: in order to avoid linker errors when using the -ObjC flag, you need to have at least one ".cpp" (C++) or ".mm" (Objective C++) source file in your own project, even if it's an empty one. If your project has ".m" (Objective C) and ".h" files only you will get linker errors because Xcode won't know that there is both C++ and Objective C code in the project.

Download link: iOS SDK

This is a 45Mb download containing the header files and compiled libraries for the simulator and device targets as a zip file. A sample map, style sheet, fonts, and tools including makemap, the map building program, are also included. It contains SDKs for both iOS on a device and and iOS on a simulator. The SDKs are in the ios folder and are delivered as .xcframework files, one for CartoType and one for the MetalANGLE graphics library. When you create an app you will need to add both the CartoType and the MetalANGLE frameworks to your app. Then you need to make sure that they are shipped with the app: select your app in Xcode, then select your build under TARGETS, then Build Phases -> Embed Frameworks, then add both CartoType.xcframework and MetalANGLE.xcframework, and tick 'Code Sign On Copy'.

(If you are upgrading to a new version of the CartoType iOS SDK, you may sometimes find that Xcode does not recognize new Objective C headers or classes. You can usually fix this problem by closing your project, opening the organizer from the Xcode Window menu, select your project, then click on 'delete' opposite 'derived data'. Then close Xcode, reopen your project, clean it and rebuild. Thanks to TigerCoding for this tip from StackOverflow.)

iOS demo program with source code

You can also download the source code and project files for a full-featured sample app with fast hardware-accelerated rendering, handling of user gestures for panning, zooming and rotation, routing using different profiles, turn by turn navigation, finding placenames and addresses, night mode, and perspective mode. You can set the start or end of a route using a long press. Other features are available from toolbar buttons.

iOS sample project

To build and run the app, open the project in Xcode on a Macintosh and add the CartoType iOS SDK to it. If you are a licensee you can use your licensed CartoType SDK instead of the evaluation version; change the call to the license() function in AppDelegate.swift so that it supplies your license key. You will need to sign the app using your Apple developer certificate.

You can then run it in the simulator or on an iOS device.

The C# (.NET) SDK

This SDK allows you to use CartoType with the .NET framework. You can use any .NET language, such as C#, VB.NET or C++/CLI. You can build a complete application using CartoType in just a few lines of code, as shown in the C# demo program included with the SDK. The .NET SDK (documented here) gives you access to all CartoType features, including map, style sheet and font loading, route calculation, navigation and address searching. It also gives access to graphics acceleration using OpenGL ES 2.0.

Download link: .NET SDK

This is a 44Mb zipped file containing a .NET DLL built for the Intel x64 platform and a C# demonstration program that uses the CartoType DLL, with its source code and data files. An XML documentation file is also supplied. As long as it is kept in the same place as the DLL it will provide tool-tip help for some of the functions.

Note: if you have trouble adding the DLL to your project, in particular if you get a message starting "could not load file or assembly ... CartoTypeWrapper.DLL", please try the following fixes: (i) right-click on CartoTypeWrapper.dll in Windows Explorer and click on 'Properties' in the context menu, then, if you see the text 'This file came from another computer and might be blocked to help protect this computer', click 'Unblock' to the right of that text; (ii) if that doesn't work try installing, or re-installing, the Visual C++ Redistributable for Visual Studio 2019 (please google that phrase to find the current download link).

cartotype dot net development screen shot

The zip file creates a single directory called CartoTypeDemo when unzipped.

Useful locations

The CartoType .NET DLL

  • release version: CartoTypeDemo\windows\bin\x64\Release\CartoTypeWrapper.dll
  • debug version: CartoTypeDemo\windows\bin\x64\Debug\CartoTypeWrapper.dll

Visual Studio solution and project files:

  • CartoTypeDemo\windows\CartoTypeDemo.sln
  • CartoTypeDemo\windows\CartoTypeDemo.csproj

Data files

  • sample map: map\isle_of_wight.ctm1
  • standard style sheet: style\standard.ctstyle
  • standard font: font\DejaVuSans.ttf

The DLLs used for graphics acceleration, libEGL.dll and libGLESvs.dll, are in the same locations as the .NET DLLs. They need to be accessible to any application using the CartoType .NET SDK.

Extra fonts are also to be found in the style and font folders. It's always a good idea to load DroidSansFallback as well as any other fonts, because it provides characters for many non-Latin scripts.

The CartoType .NET DLL will not run on non-Intel platforms because the CartoType library is compiled into native code from C++.

The Windows SDK

This SDK (documented here) supports CartoType development for desktop versions of Windows from Windows XP through Windows 8.
The CartoType Windows SDK supports development using standard Windows, or using the Qt framework.

Download link: Windows SDK

This is a 108Mb zipped file containing the CartoType header files and debug and release mode libraries for desktop Windows, built using Microsoft Visual Studio 2019 for the x64 platform.

The zip file creates a single directory called CartoType when unzipped.

Useful locations

Libraries and executables

  • release version: CartoType\bin\17.0\x64\Release\cartotype.lib
  • debug version: CartoType\bin\17.0\x64\Debug\cartotype.lib
  • tools to build maps, etc. (makemap, mapinfo, encrypt_file): CartoType\bin\17.0\x64\Release

There are also directories with the same names but with DLL appended: CartoType\bin\17.0\x64\ReleaseDLL, etc. They contain libraries linked to the C++ runtime library as a DLL, not statically. These libraries can be used with Qt. To build for Qt you will also need to link to CartoTypeQtMapRenderer.lib, which is also supplied. Qt is supported for the x64 builds only. See CartoType and Qt for detailed instructions on using Qt to build and run the sample Maps App.


  • CartoType\src\main\base; you need include only one header file, cartotype.h, to use the CartoType C++ API

Visual Studio solution and project files for the demonstration program

  • CartoType\src\demo\windows_demo\windows\CartoTypeDemo.sln

Data files

  • sample map: CartoType\map\isle_of_wight.ctm1
  • standard style sheet: CartoType\style\standard.ctstyle
  • standard font: CartoType\font\DejaVuSans.ttf

Another style sheet and extra fonts are also to be found in the style and font folders.

The Linux SDK

The C++ SDK (documented here) supports development for Linux (Ubuntu and other x11 versions) on 64-bit Intel platforms.
The Linux SDK supports developments using various GUI frameworks including Qt.

Download link: Linux SDK

This is a 23Mb zip file containing a folder called cartotype-linux-sdk, which contains the following folders:

bin: the release-mode evaluation CartoType library, and the makemap tool for creating maps, and the other tools mapinfo and encrypt_file, and (for Qt builds) the Qt map graphics-accelerated map renderer library libCartoTypeQtMapRenderer.a and other libraries needed for Qt builds.

font: standard fonts; for simple CartoType use you need load only DejaVuSans.ttf

header: the C++ header files; you need to include only header file, cartotype.h, to use CartoType

map: a sample map

style: the standard style sheet; you should load standard.ctstyle with the sample map

Linux SDK notes

  • The CartoType Linux library is built for 64-bit Intel platforms.
  • You may need to add the option -lpthread to the linker options, otherwise you might get a linker error for pthread_create.
  • Set the compiler option +std=c++14, because CartoType uses C++14.
  • If you get linker errors mentioning types in the std namespace, the cause is probably that the CartoType Linux Library is compiled using GCC 5.1 or later, and you are using GCC 4.9 or earlier.

CartoType demonstration applications

These programs are intended to show off the features of CartoType and help you decide whether the CartoType library could be a useful part of your software application.

By using the CartoType demonstration programs, maps or style sheets, however acquired, you accept the terms of the CartoType Evaluation License and you also accept that neither CartoType Ltd, nor any owners, shareholders or officers of CartoType Ltd, or any other contributors to, authors of or maintainers of the CartoType system, are liable for any damage, direct or consequential, caused by downloading, installing or using the demonstration programs, maps or style sheets, and that the demonstration programs, maps or style sheets are not warranted fit for any particular use and are for evaluation use only and may not be used for any commercial purpose.