© OpenStreetMap contributors · Protomaps · Drawn by Lettering
Writing a map engine from scratch · 4
The names on a map of central Kyoto, set by code written for this page: letters drawn from distance fields, street names that follow the street, Japanese names stacked upright on north–south streets, symbols, route shields, and every label checked against the others before it goes down.
Six steps from map data to the names on the map. Every frame, each candidate label is tried in order of importance and either goes down or is left out.
Vector tiles cut every street at the tile edge, and a name along a street needs the whole street. The tiles are first trimmed back to their own squares, which drops the overlap each tile carries, and then pieces with the same name that meet end to end are joined. Central Kyoto's 1,675 named pieces become 811 streets.
Each character is drawn once on a canvas, and for every pixel the distance to the edge of the letter is computed in two passes, columns then rows (Felzenszwalb and Huttenlocher's distance transform). The GPU cuts that field at one value to draw the letter at any size and angle, and at a lower value to draw the halo. Characters are rasterised only when a label first needs them, and packed into one atlas row by row.
edge = 0.75 halo = 0.75 − width / (8 · scale)
A street name is laid out letter by letter along the line, each letter turned to the direction of the segment it sits on. If two neighbouring letters would turn by more than 35° the spot is abandoned. If the text would run leftwards it is laid out backwards so it is never upside down, and long streets repeat their name at intervals.
Japanese maps write names down north–south streets in a column, the way Japanese is written vertically, rather than lying them on their side. When a street runs within 25° of vertical and its name is in Chinese characters or kana, the letters stay upright and stack from top to bottom. A few marks change in a column: the long-vowel mark ー, the wave dash and brackets are turned 90°.
烏丸通 → 烏 / 丸 / 通 (top to bottom)
Labels are tried in order: city, stations, major streets, rivers, route shields, temples and shrines, then smaller places and streets, and within each level the labels that were already showing go first, so the map does not flicker. Point labels try eight positions around their symbol, upper right first. Every placed box is registered in a grid of 48-pixel cells, so a new label is checked only against its neighbours.
Named parks, palaces and campuses are labelled at the point inside the area furthest from its edge, found by repeatedly splitting a grid of cells; the larger the area on screen, the larger the name. Temples, shrines, schools and post offices use the Geospatial Information Authority of Japan's map symbols: 卍, a torii, 文 and 〒 in a circle. National routes get the inverted shield and prefectural routes the hexagon.
Map data © OpenStreetMap contributors (ODbL), from the Protomaps basemap build of 19 October 2026. Map symbols drawn after the Geospatial Information Authority of Japan's chizu kigō.