Sorry, you need to enable JavaScript to visit this website.

Creating custom glyphs

Overview of the tutorial

This tutorial shows you how to create custom glyphs. In this tutorial you will do the following:

  • Create custom glyphs
  • Include new glyphs in a style for vector map

Prerequesites

  • API key
  • Npm and Node.js
  • Git

API keys

To get an API key:

 

Note - It is possible to have a single key(app) for all TomTom services, but you can also choose to have individual keys for the different services.

Introduction

Fonts used in styles (e.g. in 'text-font' attribute) need to be provided as signed distance fields serialized using Google protocol buffers. Basically, Mapbox GL JS expects that URL in the following form will point to those pbf's:

https://www.example.com/fonts/{fontstack}/{range}.pbf
 
where:
 
  • fontstack - name of a font or fonts. For example, if a particular 'text-font' attribute contained an array
    [
    "Open Sans Semibold",
    "Arial Unicode MS Bold"
    ]
    a value for this placeholder would be "Open Sans Semibold,Arial Unicode MS Bold"
  • range - unicode characters range. 65536 characters values are split into multiple ranges each 255 characters wide. For example, 0-255 or 3584-3839.
In this tutorial you will create glyphs supported by Mapbox GL JS. To make it a little bit harder your assignment includes support for two different character sets:
  • Latin - by this I mean all languages using Latin characters and its derivatives. 
  • Arabic - it covers all languages using Arabic characters

To meet this requirement a proper font needs to be chosen. Thanks for us Google provides a very versatile font called "Noto". So let's start!

... but before you start take a look at the picture below. This is a final directory structure in a root directory of this tutorial after performing all the steps below. It might be treated as a reference in case of confusion that might be caused by so many directory creation operation you are about to carry out.

Step 1. Download sample fonts

Create a directory called "glyphs-tutorial" with subdirectory "fonts".

Download the Google Noto Sans fonts from:

https://noto-website-2.storage.googleapis.com/pkgs/NotoSans-hinted.zip
https://noto-website-2.storage.googleapis.com/pkgs/NotoSansArabic-hinted.zip

Each of those fonts support different characters. "NotoSans" supports Latin characters and "NotoSansArabic" supports Arabic characters.

Next, extract these fonts to the "fonts" subdirectory created earlier.

Step 2. Setup the "fontnik" tool

In order to transform fonts in the TTF format into signed distance fields in pbf files we need to use a tool called "node-fontnik". Clone its repository from github. Navigate to "glyphs-tutorial" and type following in console terminal:

git clone https://github.com/mapbox/node-fontnik.git

After this procedure, a new directory called "node-fontnik" was created under "glyphs-tutorial". 
Build the tool by following the instructions found in its README.md file. At the time of writing this tutorial you just had to type the following (being in the "node-fontnik" directory):

npm install

Step 3. Convert fonts to pbfs

You need to create two directories which will contain pbfs for each converted font. Inside the "glyphs-tutorial" directory, create the following structure of subdirectiories:

glyphs
glyphs/NotoSansRegular
glyphs/NotoSansRegularArabic

Now you need to run "node-fontnik" - inside the "glyphs-tutorial" directory, run the following commands:

node-fontnik/bin/build-glyphs fonts/NotoSans-Regular.ttf glyphs/NotoSansRegular
node-fontnik/bin/build-glyphs fonts/NotoSansArabic-Regular.ttf glyphs/NotoSansRegularArabic/

Step 4. Setup the "glyph-pbf-composite" tool

We ended up with two separate fonts in pbfs format. In order to use them at the same time (in a single style file), you need to combine them. We will use a tool called "glyph-pbf-composite" for this purpose.

Navigate to "glyphs-tutorial" and clone the "glyph-pbf-composite" tool repository by running the following command:

git clone https://github.com/mapbox/glyph-pbf-composite.git

Go into the "glyph-pbf-composite" subdirectory and install all dependencies by typing:

npm install

Step 5. Combine the pbfs

Create a file called "combine.js" in the "glyph-pbf-composite" directory and copy the following node.js code there:

var glyphs = require('./index');
var path = require('path');
var fs = require('fs');

if (process.argv.length !== 5) {
    console.log('Expected input and output directories');
    process.exit(1);
}

var fontsDirs = process.argv[2].split(',');
var inputDir = path.resolve(process.argv[3]);
var outputDir = path.resolve(process.argv[4]);

for (var i = 0; i < 65536; (i = i + 256)) {
    var range = i + '-' + Math.min(i + 255, 65535);
    var pbfsToCombine = readPbfsFilesToCombine(inputDir, fontsDirs, range);
    var combinedGlyphs = glyphs.combine(pbfsToCombine, fontsDirs.toString());
    fs.writeFileSync(outputDir + '/' + range + '.pbf', combinedGlyphs);
}

function readPbfsFilesToCombine(inputDir, fontsDirs, range) {
    var pbfsFiles = [];
    for(var i = 0; i < fontsDirs.length; ++i) {
        var pbfFilePath = inputDir + '/' + fontsDirs[i] + '/' + range + '.pbf';
        pbfsFiles.push(fs.readFileSync(pbfFilePath));
    }
    return pbfsFiles;
}

Before launching the script, create a directory structure for the result of combining pbfs. Inside "glyphs-tutorial" directory, create the following structure of subdirectiories:

combined-glyphs
combined-glyphs/NotoSansRegularAndNotoSansRegularArabic

Now, run this new script by typing following command from inside "glyphs-tutorial" directory:

node glyph-pbf-composite/combine.js NotoSansRegular,NotoSansRegularArabic glyphs/ combined-glyphs/NotoSansRegularAndNotoSansRegularArabic

The structure of this command is: 

node glyph-pbf-composite/combine.js <comma_separated_pbf_filenames> <directory_with_pbfs> <output_file>

When this command is run successfully, the combined glyphs file should land in the output directory "combined-glyphs".

Step 6. Use generated glyphs

Although you may use the combined glyphs wherever you want, in this tutorial we will configure them to be used in the examples downloaded from https://developer.tomtom.com/maps-sdk-web/downloads.

Create the "examples" subdirectory under "glyphs-tutorial" and extract a downloaded examples package into it.

Setup the API keys as described in the following tutorial.

Finally the content of your newly created "examples" directory should look similar to the picture below:

Take a look at the "sdk" directory. It contains Maps SDK for Web. If you look inside it you should see files and directories similar to the one on a picture below:

You may notice a directory called "glyphs". Move there combined glyphs directory "NotoSansRegularAndNotoSansRegularArabic".

The last task left is to modify a style in order to use your new glyphs. In the "glyphs-tutorial" directory create another directory called "glyphs-replacer". Inside this new directory create a file called "replacer.js" and copy there the following code:

var fs = require('fs')
var path = require('path');

if (process.argv.length !== 4) {
    console.log('Expected glyphs name and styles file');
    process.exit(1);
}

var glyphsName = process.argv[2];
var stylesFilePath = path.resolve(process.argv[3]);

fs.readFile(stylesFilePath, 'utf8', function (err,data) {
  if (err) {
    return console.log(err);
  }
  var result = data.replace(/FrutigerHelveticaMYingHei-Regular/gim, glyphsName);

  fs.writeFile(stylesFilePath, result, 'utf8', function (err) {
     if (err) return console.log(err);
  });
});

Now, run this new script by typing following command from inside "glyphs-tutorial" directory:

node glyphs-replacer/replacer.js NotoSansRegularAndNotoSansRegularArabic examples/sdk/styles/basic_main.json

Now, in order to run the http server with the examples, go into the "examples" directory and type:

npm install && npm start

You can view the results by visiting: http://localhost:8080/#map-vector-basic

New glyphs based on Noto fonts look as follows:

Before changes described in this tutorial, the labels on the map would look like this:

You are here