1.. |check| unicode:: U+02713 .. CHECK MARK 2.. |Aacute| unicode:: U+000C1 .. LATIN CAPITAL LETTER A WITH ACUTE 3.. |eacute| unicode:: U+000E9 .. LATIN SMALL LETTER E WITH ACUTE 4.. |otilde| unicode:: U+000F5 .. LATIN SMALL LETTER O WITH TILDE 5.. |Utilde| unicode:: U+00168 .. LATIN CAPITAL LETTER U WITH TILDE 6.. |uuml| unicode:: U+000FC .. LATIN SMALL LETTER U WITH DIAERESIS 7.. |uml| unicode:: U+000A8 .. DIAERESIS 8 9.. _font: 10 11============== 12Font (lv_font) 13============== 14 15In LVGL fonts are collections of bitmaps and other information required 16to render images of individual letters (glyph). A font is stored in a 17:cpp:type:`lv_font_t` variable and can be set in a style's *text_font* field. 18For example: 19 20.. code-block:: c 21 22 lv_style_set_text_font(&my_style, &lv_font_montserrat_28); /* Set a larger font */ 23 24Fonts have a **format** property. It describes how the glyph data is stored. 25At this writing there are 12 possible values that this field can take, and those 26values fall into 2 categories: 27 28:Legacy simple: 1, 2, 4 or 8-bpp (aligned or unaligned) and image format, and 29:Advanced: vector, SVG, and custom formats; for the latter, the user provides 30 the rendering logic. 31 32For simple formats: 33 34- the font is stored as an array of bitmaps, one bitmap per glyph; 35- the value stored for each pixel determines the pixel's opacity, enabling edges 36 to be smoother --- higher bpp values result in smoother edges. 37 38For advanced formats, the font information is stored in its respective format. 39 40The **format** property also affects the amount of memory needed to store a 41font. For example, ``format = LV_FONT_GLYPH_FORMAT_A4`` makes a font nearly four 42times larger compared to ``format = LV_FONT_GLYPH_FORMAT_A1``. 43 44 45 46Unicode Support 47*************** 48 49LVGL supports **UTF-8** encoded Unicode characters. Your editor needs to 50be configured to save your code/text as UTF-8 (usually this the default) 51and be sure that :c:macro:`LV_TXT_ENC` is set to :c:macro:`LV_TXT_ENC_UTF8` in 52``lv_conf.h``. (This is the default value.) 53 54To test it try 55 56.. code-block:: c 57 58 lv_obj_t * label1 = lv_label_create(lv_screen_active(), NULL); 59 lv_label_set_text(label1, LV_SYMBOL_OK); 60 61If all works well, a '\ |check|\ ' character should be displayed. 62 63 64Typesetting 65*********** 66 67Although LVGL can decode and display any Unicode characters 68(assuming the font supports them), LVGL cannot correctly render 69all complex languages. 70 71The standard Latin-based languages (e.g., English, Spanish, German) 72and East Asian languages such as Chinese, Japanese, and Korean (CJK) 73are relatively straightforward, as their characters are simply 74written from left to right. 75 76Languages like Arabic, Persian, and Hebrew, which use Right-to-Left 77(RTL) or mixed writing directions, are also supported in LVGL. 78Learn more :ref:`here <bidi>`. 79 80For characters such as '|eacute|', '|uuml|', '|otilde|', '|Aacute|', and '|Utilde|', 81it is recommended to use the single Unicode format (NFC) rather than decomposing them 82into a base letter and diacritics (e.g. ``u`` + |uml|). 83 84Complex languages where subsequent characters combine into a single glyph 85and where the resulting glyph has no individual Unicode representation 86(e.g., Devanagari), have limited support in LVGL. 87 88 89 90Built-In Fonts 91************** 92 93There are several built-in fonts in different sizes, which can be 94enabled in ``lv_conf.h`` with *LV_FONT_...* defines. 95 96Normal Fonts 97------------ 98 99The following fonts contain all ASCII characters, the degree symbol (U+00B0), the 100bullet symbol (U+2022) and the built-in symbols (see below). 101 102- :c:macro:`LV_FONT_MONTSERRAT_12`: 12 px font 103- :c:macro:`LV_FONT_MONTSERRAT_14`: 14 px font 104- :c:macro:`LV_FONT_MONTSERRAT_16`: 16 px font 105- :c:macro:`LV_FONT_MONTSERRAT_18`: 18 px font 106- :c:macro:`LV_FONT_MONTSERRAT_20`: 20 px font 107- :c:macro:`LV_FONT_MONTSERRAT_22`: 22 px font 108- :c:macro:`LV_FONT_MONTSERRAT_24`: 24 px font 109- :c:macro:`LV_FONT_MONTSERRAT_26`: 26 px font 110- :c:macro:`LV_FONT_MONTSERRAT_28`: 28 px font 111- :c:macro:`LV_FONT_MONTSERRAT_30`: 30 px font 112- :c:macro:`LV_FONT_MONTSERRAT_32`: 32 px font 113- :c:macro:`LV_FONT_MONTSERRAT_34`: 34 px font 114- :c:macro:`LV_FONT_MONTSERRAT_36`: 36 px font 115- :c:macro:`LV_FONT_MONTSERRAT_38`: 38 px font 116- :c:macro:`LV_FONT_MONTSERRAT_40`: 40 px font 117- :c:macro:`LV_FONT_MONTSERRAT_42`: 42 px font 118- :c:macro:`LV_FONT_MONTSERRAT_44`: 44 px font 119- :c:macro:`LV_FONT_MONTSERRAT_46`: 46 px font 120- :c:macro:`LV_FONT_MONTSERRAT_48`: 48 px font 121 122Special fonts 123------------- 124 125- :c:macro:`LV_FONT_MONTSERRAT_28_COMPRESSED`: Same as normal 28 px font but stored as a :ref:`fonts_compressed` with 3 bpp 126- :c:macro:`LV_FONT_DEJAVU_16_PERSIAN_HEBREW`: 16 px font with normal range + Hebrew, Arabic, Persian letters and all their forms 127- :c:macro:`LV_FONT_SIMSUN_16_CJK`: 16 px font with normal range plus 1000 of the most common CJK radicals 128- :c:macro:`LV_FONT_UNSCII_8`: 8 px pixel perfect font with only ASCII characters 129- :c:macro:`LV_FONT_UNSCII_16`: 16 px pixel perfect font with only ASCII characters 130 131The built-in fonts are **global variables** with names like 132:cpp:var:`lv_font_montserrat_16` for a 16 px height font. To use them in a 133style, just add a pointer to a font variable like this: 134 135.. code-block:: c 136 137 lv_style_set_text_font(&my_style, &lv_font_montserrat_28); 138 139The built-in fonts with ``bpp = 4`` contain the ASCII characters and use 140the `Montserrat <https://fonts.google.com/specimen/Montserrat>`__ font. 141 142In addition to the ASCII range, the following symbols are also added to 143the built-in fonts from the `FontAwesome <https://fontawesome.com/>`__ 144font. 145 146.. _fonts_symbols: 147 148.. image:: /misc/symbols.png 149 150The symbols can be used singly as: 151 152.. code-block:: c 153 154 lv_label_set_text(my_label, LV_SYMBOL_OK); 155 156Or together with strings (compile time string concatenation): 157 158.. code-block:: c 159 160 lv_label_set_text(my_label, LV_SYMBOL_OK "Apply"); 161 162Or more symbols together: 163 164.. code-block:: c 165 166 lv_label_set_text(my_label, LV_SYMBOL_OK LV_SYMBOL_WIFI LV_SYMBOL_PLAY); 167 168 169 170Special Features 171**************** 172 173.. _bidi: 174 175Bidirectional support 176--------------------- 177 178Most languages use a Left-to-Right (LTR for short) writing direction, 179however some languages (such as Hebrew, Persian or Arabic) use 180Right-to-Left (RTL for short) direction. 181 182LVGL not only supports RTL text but supports mixed (a.k.a. 183bidirectional, BiDi) text rendering as well. Some examples: 184 185.. image:: /misc/bidi.png 186 187BiDi support is enabled by setting :c:macro:`LV_USE_BIDI` to a non-zero value in ``lv_conf.h``. 188 189All text has a base direction (LTR or RTL) which determines some 190rendering rules and the default alignment of the text (left or right). 191However, in LVGL, the base direction is not only applied to labels. It's 192a general property which can be set for every Widget. If not set then it 193will be inherited from the parent. This means it's enough to set the 194base direction of a screen and its child Widgets will inherit it. 195 196The default base direction for screens can be set by 197:c:macro:`LV_BIDI_BASE_DIR_DEF` in ``lv_conf.h`` and other Widgets inherit the 198base direction from their parent. 199 200To set a Widget's base direction use :cpp:expr:`lv_obj_set_style_base_dir(widget, base_dir, selector)`. 201The possible base directions are: 202 203- :cpp:enumerator:`LV_BASE_DIR_LTR`: Left to Right base direction 204- :cpp:enumerator:`LV_BASE_DIR_RTL`: Right to Left base direction 205- :cpp:enumerator:`LV_BASE_DIR_AUTO`: Auto detect base direction 206 207This list summarizes the effect of RTL base direction on Widgets: 208 209- Create Widgets by default on the right 210- ``lv_tabview``: Displays tabs from right to left 211- ``lv_checkbox``: Shows the box on the right 212- ``lv_buttonmatrix``: Orders buttons from right to left 213- ``lv_list``: Shows icons on the right 214- ``lv_dropdown``: Aligns options to the right 215- The text strings in ``lv_table``, ``lv_buttonmatrix``, ``lv_keyboard``, ``lv_tabview``, 216 ``lv_dropdown``, ``lv_roller`` are "BiDi processed" to be displayed correctly 217 218Arabic and Persian support 219-------------------------- 220 221There are some special rules to display Arabic and Persian characters: 222the *form* of a character depends on its position in the text. A 223different form of the same letter needs to be used when it is isolated, 224at start, middle or end positions. Besides these, some conjunction rules 225should also be taken into account. 226 227LVGL supports these rules if :c:macro:`LV_USE_ARABIC_PERSIAN_CHARS` is enabled 228in ``lv_conf.h``. 229 230However, there are some limitations: 231 232- Only displaying text is supported (e.g. on labels), i.e. text inputs (e.g. Text 233 Area) do not support this feature. 234- Static text (i.e. const) is not processed. E.g. text set by :cpp:func:`lv_label_set_text` 235 will be "Arabic processed" but :cpp:func:`lv_label_set_text_static` will not. 236- Text get functions (e.g. :cpp:func:`lv_label_get_text`) will return the processed text. 237 238.. _fonts_compressed: 239 240Compressed fonts 241---------------- 242 243The built-in font engine supports compressed bitmaps. 244Compressed fonts can be generated by 245 246- ticking the ``Compressed`` check box in the online converter 247- not passing the ``--no-compress`` flag to the offline converter (compression is applied by default) 248 249Compression is more effective with larger fonts and higher bpp. However, 250it's about 30% slower to render compressed fonts. Therefore, it is 251recommended to compress only the largest fonts of a user interface, 252because 253 254- they need the most memory 255- they can be compressed better 256- and on the likelihood that they are used less frequently than the medium-sized 257 fonts, the performance cost will be smaller. 258 259Compressed fonts also support ``bpp=3``. 260 261Kerning 262------- 263 264Fonts may provide kerning information to adjust the spacing between specific 265characters. 266 267- The online converter generates kerning tables. 268- The offline converter generates kerning tables unless ``--no-kerning`` is 269 specified. 270- FreeType integration does not currently support kerning. 271- The Tiny TTF font engine supports GPOS (Glyph Positioning) and Kern tables. 272 273To configure kerning at runtime, use :cpp:func:`lv_font_set_kerning`. 274 275 276 277.. _add_font: 278 279Adding a New Font 280***************** 281 282There are several ways to add a new font to your project: 283 2841. The simplest method is to use the `Online font converter <https://lvgl.io/tools/fontconverter>`__. 285 Just set the parameters, click the *Convert* button, copy the font to your project 286 and use it. **Be sure to carefully read the steps provided on that site 287 or you will get an error while converting.** 2882. Use the `Offline font converter <https://github.com/lvgl/lv_font_conv>`__. 289 (Requires Node.js to be installed) 2903. If you want to create something like the built-in 291 fonts (Montserrat font and symbols) but in a different size and/or 292 ranges, you can use the ``built_in_font_gen.py`` script in 293 ``lvgl/scripts/built_in_font`` folder. (This requires Python and 294 https://github.com/lvgl/lv_font_conv/ to be installed.) 295 296To declare a font in a file, use :cpp:expr:`LV_FONT_DECLARE(my_font_name)`. 297 298To make fonts globally available (like the built-in fonts), add them to 299:c:macro:`LV_FONT_CUSTOM_DECLARE` in ``lv_conf.h``. 300 301 302 303Adding New Symbols 304****************** 305 306The built-in symbols are created from the `FontAwesome <https://fontawesome.com/>`__ font. 307 3081. Search for a symbol on https://fontawesome.com. For example the 309 `USB symbol <https://fontawesome.com/icons/usb?style=brands>`__. Copy its 310 Unicode ID which is ``0xf287``. 3112. Open the `Online font converter <https://lvgl.io/tools/fontconverter>`__. 312 Add `FontAwesome.woff <https://lvgl.io/assets/others/FontAwesome5-Solid+Brands+Regular.woff>`__. 3133. Set the parameters such as Name, Size, BPP. You'll use this name to 314 declare and use the font in your code. 3154. Add the Unicode ID of the symbol to the range field. E.g.\ ``0xf287`` 316 for the USB symbol. More symbols can be enumerated with ``,``. 3175. Convert the font and copy the generated source code to your project. 318 Make sure to compile the ``.c`` file of your font. 3196. Declare the font using ``extern lv_font_t my_font_name;`` or simply 320 use :cpp:expr:`LV_FONT_DECLARE(my_font_name)`. 321 322**Using the symbol** 323 3241. Convert the Unicode value to UTF8, for example on 325 `this site <http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=f287&mode=hex>`__. 326 For ``0xf287`` the *Hex UTF-8 bytes* are ``EF 8A 87``. 3272. Create a ``#define`` string from the UTF8 values: ``#define MY_USB_SYMBOL "\xEF\x8A\x87"`` 3283. Create a label and set the text. Eg. :cpp:expr:`lv_label_set_text(label, MY_USB_SYMBOL)` 329 330:note: :cpp:expr:`lv_label_set_text(label, MY_USB_SYMBOL)` searches for this symbol 331 in the font defined in the style's ``text.font`` property. To use the symbol 332 you will need to set the style's text font to use the generated font, e.g. 333 :cpp:expr:`lv_style_set_text_font(&my_style, &my_font_name)` or 334 :cpp:expr:`lv_obj_set_style_text_font(label, &my_font_name, 0)`. 335 336 337 338Loading a Font at Run-Time 339************************** 340 341:cpp:func:`lv_binfont_create` can be used to load a font from a file. The font needs 342to have a special binary format. (Not TTF or WOFF). Use 343`lv_font_conv <https://github.com/lvgl/lv_font_conv/>`__ with the 344``--format bin`` option to generate an LVGL compatible font file. 345 346:note: To load a font :ref:`LVGL's filesystem <overview_file_system>` 347 needs to be enabled and a driver must be added. 348 349Example 350 351.. code-block:: c 352 353 lv_font_t *my_font = lv_binfont_create("X:/path/to/my_font.bin"); 354 if(my_font == NULL) return; 355 356 /* Use the font */ 357 358 /* Free the font if not required anymore */ 359 lv_binfont_destroy(my_font); 360 361 362 363Loading a Font from a Memory Buffer at Run-Time 364*********************************************** 365 366:cpp:func:`lv_binfont_create_from_buffer` can be used to load a font from a memory buffer. 367This function may be useful to load a font from an external file system, which is not 368supported by LVGL. The font needs to be in the same format as if it were loaded from a file. 369 370:note: To load a font from a buffer :ref:`LVGL's filesystem <overview_file_system>` 371 needs to be enabled and the MEMFS driver must be added. 372 373Example 374 375.. code-block:: c 376 377 lv_font_t *my_font; 378 uint8_t *buf; 379 uint32_t bufsize; 380 381 /* Read font file into the buffer from the external file system */ 382 ... 383 384 /* Load font from the buffer */ 385 my_font = lv_binfont_create_from_buffer((void *)buf, buf)); 386 if(my_font == NULL) return; 387 /* Use the font */ 388 389 /* Free the font if not required anymore */ 390 lv_binfont_destroy(my_font); 391 392 393Using a BDF Font 394**************** 395 396Small displays with low resolution don't look pretty with automatically rendered fonts. A bitmap font provides 397the solution, but it's necessary to convert the bitmap font (BDF) to a TTF. 398 399Convert BDF to TTF 400------------------ 401 402BDF are bitmap fonts where fonts are not described in outlines but in pixels. BDF files can be used but 403they must be converted into the TTF format using ``mkttf``, which can be found 404in this GitHub repository: https://github.com/Tblue/mkttf . This tool uses potrace to generate outlines from 405the bitmap information. The bitmap itself will be embedded into the TTF as well. `lv_font_conv <https://github.com/lvgl/lv_font_conv/>`__ uses 406the embedded bitmap but it also needs the outlines. One might think you can use a fake MS Bitmap 407only sfnt (ttf) (TTF without outlines) created by fontforge, but this will not work. 408 409Install imagemagick, python3, python3-fontforge and potrace 410 411On Ubuntu Systems, just type 412 413.. code:: bash 414 415 sudo apt install imagemagick python3-fontforge potrace 416 417Clone mkttf 418 419.. code:: bash 420 421 git clone https://github.com/Tblue/mkttf 422 423Read the mkttf docs. 424 425Former versions of imagemagick needs the imagemagick call in front of convert, identify and so on. 426But newer versions don't. So you might want to change 2 lines in ``potrace-wrapper.sh`` --- 427open ``potrace-wrapper.sh`` and remove imagemagick from line 55 and line 64: 428 429line 55 430 431.. code:: bash 432 433 wh=($(identify -format '%[width]pt %[height]pt' "${input?}")) 434 435line 64 436 437.. code:: bash 438 439 convert "${input?}" -sample '1000%' - \ 440 441It might be necessary to change the mkttf.py script. 442 443line 1 444 445.. code:: bash 446 447 #!/usr/bin/env python3 448 449Example for a 12px font 450----------------------- 451 452.. code-block:: console 453 454 cd mkttf 455 ./mkttf.py ./TerminusMedium-12-12.bdf 456 Importing bitmaps from 0 additional fonts... 457 Importing font `./TerminusMedium-12-12.bdf' into glyph background... 458 Processing glyphs... 459 Saving TTF file... 460 Saving SFD file... 461 Done! 462 463The TTF ``TerminusMedium-001.000.ttf`` will be created from ``./TerminusMedium-12-12.bdf``. 464 465To create a font for LVGL: 466 467.. code:: bash 468 469 lv_font_conv --bpp 1 --size 12 --no-compress --font TerminusMedium-001.000.ttf --range 0x20-0x7e,0xa1-0xff --format lvgl -o terminus_1bpp_12px.c 470 471:note: use 1-bpp because we don't use anti-aliasing. It doesn't look sharp on displays with a low resolution. 472 473 474 475Adding a New Font Engine 476************************ 477 478LVGL's font interface is designed to be very flexible but, even so, you 479can add your own font engine in place of LVGL's internal one. For 480example, you can use `FreeType <https://www.freetype.org/>`__ to 481real-time render glyphs from TTF fonts or use an external flash to store 482the font's bitmap and read them when the library needs them. FreeType can be used in LVGL as described in :ref:`Freetype <freetype>`. 483 484To add a new font engine, a custom :cpp:type:`lv_font_t` variable needs to be created: 485 486.. code-block:: c 487 488 /* Describe the properties of a font */ 489 lv_font_t my_font; 490 my_font.get_glyph_dsc = my_get_glyph_dsc_cb; /* Set a callback to get info about glyphs */ 491 my_font.get_glyph_bitmap = my_get_glyph_bitmap_cb; /* Set a callback to get bitmap of a glyph */ 492 my_font.line_height = height; /* The real line height where any text fits */ 493 my_font.base_line = base_line; /* Base line measured from the top of line_height */ 494 my_font.dsc = something_required; /* Store any implementation specific data here */ 495 my_font.user_data = user_data; /* Optionally some extra user data */ 496 497 ... 498 499 /* Get info about glyph of `unicode_letter` in `font` font. 500 * Store the result in `dsc_out`. 501 * The next letter (`unicode_letter_next`) might be used to calculate the width required by this glyph (kerning) 502 */ 503 bool my_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) 504 { 505 /* Your code here */ 506 507 /* Store the result. 508 * For example ... 509 */ 510 dsc_out->adv_w = 12; /* Horizontal space required by the glyph in [px] */ 511 dsc_out->box_h = 8; /* Height of the bitmap in [px] */ 512 dsc_out->box_w = 6; /* Width of the bitmap in [px] */ 513 dsc_out->ofs_x = 0; /* X offset of the bitmap in [pf] */ 514 dsc_out->ofs_y = 3; /* Y offset of the bitmap measured from the as line */ 515 dsc_out->format= LV_FONT_GLYPH_FORMAT_A2; 516 517 return true; /* true: glyph found; false: glyph was not found */ 518 } 519 520 521 /* Get the bitmap of `unicode_letter` from `font`. */ 522 const uint8_t * my_get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter) 523 { 524 /* Your code here */ 525 526 /* The bitmap should be a continuous bitstream where 527 * each pixel is represented by `bpp` bits */ 528 529 return bitmap; /* Or NULL if not found */ 530 } 531 532 533 534Using Font Fallback 535******************* 536 537If the font in use does not have a glyph needed in a text-rendering task, you can 538specify a ``fallback`` font to be used in :cpp:type:`lv_font_t`. 539 540``fallback`` can be chained, so it will try to solve until there is no ``fallback`` set. 541 542.. code-block:: c 543 544 /* Roboto font doesn't have support for CJK glyphs */ 545 lv_font_t *roboto = my_font_load_function(); 546 /* Droid Sans Fallback has more glyphs but its typeface doesn't look good as Roboto */ 547 lv_font_t *droid_sans_fallback = my_font_load_function(); 548 /* So now we can display Roboto for supported characters while having wider characters set support */ 549 roboto->fallback = droid_sans_fallback; 550 551 552 553.. _fonts_api: 554 555API 556*** 557