How to draw russian (cyrillic) characters in LibGDX

When we develop for mobile devices, we have to keep in mind that propably our program will be used in several countries for users of diferent languages. A tool to facilitate the use of our software for these users is to translate our application into the local language of each user. This process is known as Internacionalization (I18N) and Localization (L10N). To know more about how to implement this in LibGDX, you can go to Official Wiki.

On the other hand, one of the options provided to us LibGDX is to can work with TrueType fonts (.ttf) through the extension gdx-freetype. To know more about how to use these fonts, you can go to LibGDX Wiki.

By combining both tools (I18N / L10N and TTF fonts), we find that:

  1. Each language uses a particular alphabet. This is, in brief, the set of letters and spellings that are used to represent the language in written form.
  2. Typically, a font supports only a given set of letters or spellings.

As result of the above two points, probably we need to use more than one TTF font for showing our program in determined languages. Next, we are going to show an use case by using as example the text “Hello World!” translated to spanish and russian. It’s possible to work with other alphabets in a similar way.

Important:

  1. This is not a tutorial about internacionalization nor localization. It simply shows how to draw texts in LibGDX from diferent alphabets with TTF fonts.
  2. Gdx-freetype works with UTF-8, so we need to use this encoding for the files of our project.
  3. You can get source code at GitHub.

 

Creating the project (gdx-freetype)

The first step is to create the project in LibGDX. We know we will work with TTF fonts, so it’s needed the check of the gdx-freetype extension.

In this case I will call the project Gdx-Freetype-Example. Note:

  1. In this project we will not use the physics library Box2d. Then unckeck that option.
  2. We enable the extension Freetype, in section “Extensions”.
  3. Freetype does not support HTML project, so we have to uncheck this project generation.
freetype_project_generator
LibGDX Project Generator

For this project I have used this values:

  • Name: Gdx-Freetype-Example
  • Package: com.pixnbgames.gdx_freetype_example
  • Game class: GdxGameFreetypeExampleGame

If we have done it well, when we import this project in our IDE, we can see the gdx-freetype as dependeces of the project:

gdx-freetype libs
gdx-freetype libs

 

Selecting fonts

I have said that we will work with Spanish and Russian languages. In this example, we simply are going to draw a welcome message on screen:

  • Spanish: ¡Hola Mundo!
  • Russian: Привет мир!

If we see the message translated to russian, it can be a little bit strange for us. This is because, while Spanish uses the latin alphabet, Russian language uses a variant of cyrillic alphabet.

Normally, a TTF font supports only a set of all existing alphabets, so we have to select several fonts depending of the language we have to represent. In this case, we will use this fonts:

 

Add fonts to our LibGDX project

When we download these fonts, we can have more than one TTF file. Each of these TTF file is for a font style (bold, italic, …) For this example, we only use a file from each font (“goodfish rg.ttf” from Goodish y “Imperial Web.ttf” from Imperial One).

These TTF files are another resource of our project, so we add them to directory “assets/” on the android project. To keep a good organization for our resources, we can create a specific folder, for example called “fonts/“, inside directory “assets/” and add here our fonts:

android/assets/font
android/assets/font

 

Generate TTF font for LibGDX

Before render text with our TTF fonts, we need to generate Bitmap fonts. We create the class FontFactory for centralization of font generation. The source code of this class is so long to paste it here, so we will see it by parts.

At first place, we have two static variables of type String with the name of TTF files:

13
14
public static final String SPANISH_FONT_NAME = "fonts/goodfish rg.ttf";
public static final String RUSSIAN_FONT_NAME = "fonts/Imperial Web.ttf";

Next, we will have a static variable to contain russian characters. Why is this? By default, LibGDX will generate a font with characters contained in the string FreeTypeFontGenerator.DEFAULT_CHARS. This String contains only the latin characters, so if we want to generate other kind of chars we have to say to LibGDX which chars are these. In this example, we will use the below String that contains the russian alphabet:

17
18
19
public static final String RUSSIAN_CHARACTERS = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
                                              + "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"
                                              + "1234567890.,:;_¡!¿?\"'+-*/()[]={}";

Generated fonts are stored at two local variables:

24
25
private BitmapFont esFont;
private BitmapFont ruFont;

The next method is responsible of generating of Bitmap font:

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
private BitmapFont generateFont(String fontName, String characters) {
 
    // Configure font parameters
    FreeTypeFontParameter parameter = new FreeTypeFontParameter();
    parameter.characters = characters;
    parameter.size = 24;
 
    // Generate font
    FreeTypeFontGenerator generator = new FreeTypeFontGenerator( Gdx.files.internal(fontName) );
    BitmapFont font = generator.generateFont(parameter);
 
    // Dispose resources
    generator.dispose();
 
    return font;
}

and it will be called from initialize():

37
38
39
40
41
42
43
44
public void initialize() {
    // If fonts are already generated, dispose it!
    if (esFont != null) esFont.dispose();
    if (ruFont != null) ruFont.dispose();
 
    esFont = generateFont(SPANISH_FONT_NAME, FreeTypeFontGenerator.DEFAULT_CHARS);
    ruFont = generateFont(RUSSIAN_FONT_NAME, RUSSIAN_CHARACTERS);
}

At last, we use the method getFont() to get the font setted for the language which we receive by param:

77
78
79
80
81
public BitmapFont getFont(Locale locale) {
    if      ("es".equals(locale.getLanguage())) return esFont;
    else if ("ru".equals(locale.getLanguage())) return ruFont;
    else throw new IllegalArgumentException("Not supported language");
}

 

Drawing text on screen

in the main class, GdxGameFreetypeExampleGame, we’ll draw the message “Hello World!” translated in both Spanish and Russian. The messages are stored in two static variables:

14
15
public static final String SPANISH_MESSAGE = "¡Hola Mundo!";
public static final String RUSSIAN_MESSAGE = "Привет мир!";

Also we have two Locale objects to store localization fon Spain and Russian:

21
22
private Locale esLocale;
private Locale ruLocale;

In method create(), we initialize our font factory and Locale objects for Spain and Russia:

25
26
27
28
29
30
31
32
33
34
public void create () {
    batch = new SpriteBatch();
 
    // Initialize FontFactory
    FontFactory.getInstance().initialize();
 
    // Initialize locales
    esLocale = new Locale("es", "ES");
    ruLocale = new Locale("ru", "RU");
}

At last, we draw in the method render() using our BitmapFont from FontFactory:

37
38
39
40
41
42
43
44
45
46
47
public void render () {
    // Clear screen
    Gdx.gl.glClearColor(0, 0, 1, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
 
    // Draw with fonts
    batch.begin();
    FontFactory.getInstance().getFont(esLocale).draw(batch, SPANISH_MESSAGE, 110.f, 150.f);
    FontFactory.getInstance().getFont(ruLocale).draw(batch, RUSSIAN_MESSAGE, 70.f, 100.f);
    batch.end();
}

Result

The result of executing our code is similar to this:

freetype_example

As you can see, the message is correctly show in both languages; each of them with the font we have set for it.

Improvements:

Below there are some improvements which I have not handled in order to don’t do this tutorial too long 🙂

  • Although in this example we show a string in two languages, normally when we have a localized application we only load one of the possible languages, so would only be necessary to generate a font ever.
  • There are fonts which support several languages. Using any of these fonts, we can use same font for different languages. By this we can save disk space, something very appreciated in mobile devices.

Source code

You can get the source code at GitHub.

2 thoughts on “How to draw russian (cyrillic) characters in LibGDX

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*