Font: document new font features (#3596)

* Document new font features

* Add entry in index.rst

* Update components/display/fonts.rst

Co-authored-by: Keith Burzinski <kbx81x@gmail.com>

* Make html-strict happy

---------

Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
This commit is contained in:
Clyde Stubbs 2024-03-11 20:03:42 +11:00 committed by GitHub
parent e895ebbc30
commit 7d53484c83
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 201 additions and 122 deletions

View File

@ -0,0 +1,145 @@
.. _display-fonts:
Font Renderer Component
=======================
.. seo::
:description: Instructions for setting up fonts in ESPHome.
:image: format-font.svg
ESPHome's graphical rendering engine also has a powerful font drawer which integrates seamlessly into the system. You have the option to use **any** OpenType/TrueType (``.ttf``, ``.otf``, ``.woff``) font file at **any** size, as well as fixed-size `PCF <https://en.wikipedia.org/wiki/Portable_Compiled_Format>`_ and `BDF <https://en.wikipedia.org/wiki/Glyph_Bitmap_Distribution_Format>`_ bitmap fonts.
These fonts can be used in ESPHome's :ref:`own rendering engine <display-engine>`.
To use fonts you first have to define a font object in your ESPHome configuration file. Just grab a ``.ttf``, ``.otf``, ``.woff``, ``.pcf``, or ``.bdf`` file from somewhere on the internet and place it, for example, inside a ``fonts`` folder next to your configuration file.
Next, create a ``font:`` section in your configuration:
.. code-block:: yaml
# Various ways to configure fonts
font:
- file: "fonts/Comic Sans MS.ttf"
id: my_font
size: 20
bpp: 2
- file: "fonts/tom-thumb.bdf"
id: tomthumb
# gfonts://family[@weight]
- file: "gfonts://Roboto"
id: roboto_20
size: 20
- file:
type: gfonts
family: Roboto
weight: 900
id: roboto_16
size: 16
- file: "gfonts://Material+Symbols+Outlined"
id: icons_50
size: 50
glyphs: ["\U0000e425"] # mdi-timer
- file: "fonts/RobotoCondensed-Regular.ttf"
id: roboto_special_28
size: 28
bpp: 4
glyphs: [
a,A,á,Á,e,E,é,É,
(,),+,-,_,.,°,•,µ,
"\u0020", #space
"\u0021", #!
"\u0022", #"
"\u0027", #'
]
- file: "fonts/RobotoCondensed-Regular.ttf"
id: my_font_with_icons
size: 20
bpp: 4
extras:
- file: "fonts/materialdesignicons-webfont.ttf"
glyphs: [
"\U000F02D1", # mdi-heart
"\U000F05D4", # mdi-airplane-landing
]
display:
# ...
Configuration variables:
------------------------
- **file** (**Required**, string): The path (relative to where the .yaml file is) of the font
file. You can also use the ``gfonts://`` short form to use Google Fonts, or use the below structure:
- **type** (**Required**, string): Can be ``local`` or ``gfonts``.
**Local Fonts**:
- **path** (**Required**, string): The path (relative to where the .yaml file is) of the OpenType/TrueType or bitmap font file.
**Google Fonts**:
Each Google Font will be downloaded once and cached for future use. This can also be used to download Material
Symbols or Icons as in the example above.
- **family** (**Required**, string): The name of the Google Font family.
- **italic** (*Optional*, boolean): Whether the font should be italic.
- **weight** (*Optional*, enum): The weight of the font. Can be either the text name or the integer value:
- **thin**: 100
- **extra-light**: 200
- **light**: 300
- **regular**: 400 (**default**)
- **medium**: 500
- **semi-bold**: 600
- **bold**: 700
- **extra-bold**: 800
- **black**: 900
- **id** (**Required**, :ref:`config-id`): The ID with which you will be able to reference the font later
in your display code.
- **size** (*Optional*, int): The size of the font in pt (not pixel!).
If you want to use the same font in different sizes, create two font objects. Note: *size* is ignored
by bitmap fonts. Defaults to ``20``.
- **bpp** (*Optional*, int): The bit depth of the rendered font from OpenType/TrueType, for anti-aliasing. Can be ``1``, ``2``, ``4``, ``8``. Defaults to ``1``.
- **glyphs** (*Optional*, list): A list of characters you plan to use. Only the characters you specify
here will be compiled into the binary. Adjust this if you need some special characters or want to
reduce the size of the binary if you don't plan to use some glyphs. You can also specify glyphs by their codepoint (see below). Defaults to ``!"%()+=,-_.:°/?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz``.
- **extras** (*Optional*, enum): A list of font glyph configurations you'd like to include within this font, from other OpenType/TrueType files (eg. icons from other font, but at the same size as the main font):
- **file** (**Required**, string): The path of the font file with the extra glyphs.
- **glyphs** (**Required**, list): A list of glyphs you want to include. Can't repeat the same glyph codepoint if it was declared in the level above.
.. note::
OpenType/TrueType font files offer icons at codepoints far from what's reachable on a standard keyboard, for these it's needed
to specify the unicode codepoint of the glyph as a hex address escaped with ``\u`` or ``\U``.
- Code points up to ``0xFFFF`` are encoded like ``\uE6E8``. Lowercase ``\u`` and exactly 4 hexadecimal digits.
- Code points above ``0xFFFF`` are encoded like ``\U0001F5E9``. Capital ``\U`` and exactly 8 hexadecimal digits.
The ``extras`` section only supports OpenType/TrueType files, ``size`` and ``bpp`` will be the same as the above level. This will allow printing icons alongside the characters in the same string, like ``I \uF004 You \uF001``.
Many font sizes with multiple glyphs at high bit depths will increase the binary size considerably. Make your choices carefully.
.. note::
To use fonts you will need to have the python ``pillow`` package installed, as ESPHome uses that package
to translate the OpenType/TrueType and bitmap font files into an internal format. If you're running this as a Home Assistant add-on or with the official ESPHome docker image, it should already be installed. Otherwise you need
to install it using ``pip install "pillow==10.2.0"``.
See Also
--------
- :apiref:`display/display_buffer.h`
- :ref:`display-engine`
- `MDI cheatsheet <https://pictogrammers.com/library/mdi/>`_
- `MDI font repository <https://github.com/Pictogrammers/pictogrammers.github.io/tree/main/%40mdi/font/>`_
- :ghedit:`Edit`

View File

@ -9,10 +9,10 @@ The ``display`` component houses ESPHome's powerful rendering and display
engine. Fundamentally, there are these types of displays: engine. Fundamentally, there are these types of displays:
- Text based displays like :doc:`7-Segment displays <max7219>` or - Text based displays like :doc:`7-Segment displays <max7219>` or
:doc:`some LCD displays <lcd_display>`. :doc:`LCD displays <lcd_display>`.
- Displays like the :doc:`nextion` that have their own processors for rendering. - Graphical serial displays like :doc:`nextion` that have their own processors for rendering.
- Binary displays which can toggle ON/OFF any pixel, like :doc:`E-Paper displays <waveshare_epaper>` or - Graphical binary displays which can toggle ON/OFF any pixel, like :doc:`E-Paper <waveshare_epaper>`,
:doc:`OLED displays <ssd1306>`. :doc:`OLED <ssd1306>` or :doc:`TFT <ili9xxx>` displays.
For the last type, ESPHome has a powerful rendering engine that can do For the last type, ESPHome has a powerful rendering engine that can do
many things like draw some basic shapes, print text with any font you want, or even show images. many things like draw some basic shapes, print text with any font you want, or even show images.
@ -24,11 +24,6 @@ using an API that is designed to
- be simple and to be used without programming experience - be simple and to be used without programming experience
- but also be flexible enough to work with more complex tasks like displaying an analog clock. - but also be flexible enough to work with more complex tasks like displaying an analog clock.
.. note::
Display hardware is complex and sometimes doesn't behave as expected. If you're having trouble with your display,
please see :ref:`troubleshooting` below.
.. _display-engine: .. _display-engine:
Display Rendering Engine Display Rendering Engine
@ -38,6 +33,11 @@ In this section we will be discussing how to use ESPHome's display rendering eng
and some basic commands. Please note that this only applies to displays that can control each pixel and some basic commands. Please note that this only applies to displays that can control each pixel
individually. individually.
.. note::
Display hardware is complex and sometimes doesn't behave as expected. If you're having trouble with your display,
please see :ref:`troubleshooting` below.
So, first a few basics: When setting up a display platform in ESPHome there will be a configuration So, first a few basics: When setting up a display platform in ESPHome there will be a configuration
option called ``lambda:`` which will be called every time ESPHome wants to re-render the display. option called ``lambda:`` which will be called every time ESPHome wants to re-render the display.
In each cycle, the display is automatically cleared before the lambda is executed. You can disable In each cycle, the display is automatically cleared before the lambda is executed. You can disable
@ -72,7 +72,7 @@ x always represents the horizontal axis (width) and y the vertical axis (height)
the rendering engine is always first specify the ``x`` coordinate and then the ``y`` coordinate. the rendering engine is always first specify the ``x`` coordinate and then the ``y`` coordinate.
Basic Shapes Basic Shapes
************ ------------
Now that you know a bit more about ESPHome's coordinate system, let's draw some basic shapes like lines, rectangles Now that you know a bit more about ESPHome's coordinate system, let's draw some basic shapes like lines, rectangles
and circles: and circles:
@ -159,110 +159,14 @@ Additionally, you have access to two helper methods which will fetch the width a
You can view the full API documentation for the rendering engine in the "API Reference" in the See Also section. You can view the full API documentation for the rendering engine in the "API Reference" in the See Also section.
.. _display-fonts:
Fonts
*****
The rendering engine also has a powerful font drawer which integrates seamlessly into ESPHome.
Whereas in most Arduino display projects you have to use one of a few pre-defined fonts in very
specific sizes, with ESPHome you have the option to use **any** TrueType (``.ttf``) font file
at **any** size, as well as fixed-size `PCF <https://en.wikipedia.org/wiki/Portable_Compiled_Format>`_ and `BDF <https://en.wikipedia.org/wiki/Glyph_Bitmap_Distribution_Format>`_ bitmap fonts! Granted the reason for it is
actually not having to worry about the licensing of font files :)
To use fonts you first have to define a font object in your ESPHome configuration file. Just grab
a ``.ttf``, ``.pcf``, or ``.bdf`` file from somewhere on the internet and place it, for example,
inside a ``fonts`` folder next to your configuration file.
Next, create a ``font:`` section in your configuration:
.. code-block:: yaml
font:
- file: "fonts/Comic Sans MS.ttf"
id: my_font
size: 20
# gfonts://family[@weight]
- file: "gfonts://Roboto"
id: roboto
size: 20
- file:
type: gfonts
family: Roboto
weight: 900
id: font2
size: 16
- file: "fonts/tom-thumb.bdf"
id: tomthumb
- file: 'gfonts://Material+Symbols+Outlined'
id: icon_font_50
size: 50
glyphs: ["\U0000e425"] # mdi-timer
display:
# ...
Configuration variables:
- **file** (**Required**): The path (relative to where the .yaml file is) of the font
file. You can use the ``gfonts://`` short form to use Google Fonts, or use the below structure:
- **type** (**Required**, string): Can be ``gfonts`` or ``local``.
**Google Fonts**:
Each Google Font will be downloaded once and cached for future use. This can also be used to download Material
Symbols or Icons as in the example above.
- **family** (**Required**, string): The name of the Google Font family.
- **weight** (*Optional*, enum): The weight of the font. Can be either the text name or the integer value:
- **thin**: 100
- **extra-light**: 200
- **light**: 300
- **regular**: 400 (**default**)
- **medium**: 500
- **semi-bold**: 600
- **bold**: 700
- **extra-bold**: 800
- **black**: 900
- **italic** (*Optional*, boolean): Whether the font should be italic.
**Local Fonts**:
- **path** (**Required**, string): The path (relative to where the .yaml file is) of the TrueType or bitmap font file.
- **id** (**Required**, :ref:`config-id`): The ID with which you will be able to reference the font later
in your display code.
- **size** (*Optional*, int): The size of the font in pt (not pixel!).
If you want to use the same font in different sizes, create two font objects. Note: *size* is ignored
by bitmap fonts. Defaults to ``20``.
- **glyphs** (*Optional*, list): A list of characters you plan to use. Only the characters you specify
here will be compiled into the binary. Adjust this if you need some special characters or want to
reduce the size of the binary if you don't plan to use some glyphs. The items in the list can also
be more than one character long if you for example want to use font ligatures. Defaults to
``!"%()+=,-_.:°/?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz``.
.. note::
To use fonts you will need to have the python ``pillow`` package installed, as ESPHome uses that package
to translate the TrueType and bitmap font files into an internal format. If you're running this as a Home Assistant
add-on or with the official ESPHome docker image, it should already be installed. Otherwise you need
to install it using
``pip install "pillow==10.1.0"``.
.. _display-static_text: .. _display-static_text:
Drawing Static Text Drawing Static Text
******************* -------------------
In your display code, you can render static text by referencing the font and just entering your string: To be able to display text, you need to prepare some fonts. ESPHome's :ref:`font renderer <display-fonts>` allows you to use OpenType/TrueType/Bitmap fonts for your texts. This is very flexiblle because you can prepare various sets of fonts at different sizes with a different number of glyphs which is extremely convenient when we're talking about flash space.
In your display code, you can render static text by referencing the font and just entering your string enclosed in double quotes:
.. code-block:: yaml .. code-block:: yaml
@ -303,11 +207,21 @@ As with basic shapes, you can also specify a color for the text:
// Syntax is always: it.print(<x>, <y>, <font>, [color=COLOR_ON], [align=TextAlign::TOP_LEFT], <text>); // Syntax is always: it.print(<x>, <y>, <font>, [color=COLOR_ON], [align=TextAlign::TOP_LEFT], <text>);
it.print(0, 0, id(my_font), COLOR_ON, "Left aligned"); it.print(0, 0, id(my_font), COLOR_ON, "Left aligned");
In case of fonts rendered at higher bit depths, the background color has to be specified after the text in order for antialiasing to work:
.. code-block:: yaml
display:
- platform: ...
# ...
lambda: |-
// Syntax is always: it.print(<x>, <y>, <font>, [color=COLOR_ON], [align], <text>, [color=COLOR_OFF]);
it.print(0, 0, id(my_font_with_icons), COLOR_ON, TextAlign::CENTER, "Just\U000f05d4here. Already\U000F02D1this.", COLOR_OFF);
.. _display-printf: .. _display-printf:
Formatted Text Formatted Text
************** --------------
Static text by itself is not too impressive. What we really want is to display *dynamic* content like sensor values Static text by itself is not too impressive. What we really want is to display *dynamic* content like sensor values
on the display!. That's where ``printf`` comes in. ``printf`` is a formatting engine from the C era and ESPHome on the display!. That's where ``printf`` comes in. ``printf`` is a formatting engine from the C era and ESPHome
@ -357,7 +271,7 @@ Another interesting format string is ``%7.2f``, which would become the right-jus
- ``.2`` - round the decimal number to ``2`` digits after the decimal point. - ``.2`` - round the decimal number to ``2`` digits after the decimal point.
- ``f`` - specifier: f(loat). - ``f`` - specifier: f(loat).
You can even have as many format strings as you want in a single printf call. Just make sure the put the You can even have as many formatted items as you want in a single printf call. Just make sure the put the
arguments after the format string in the right order. arguments after the format string in the right order.
.. code-block:: yaml .. code-block:: yaml
@ -379,6 +293,19 @@ To display a text string from a ``text_sensor``, append ``.c_str()`` to the end
lambda: |- lambda: |-
it.printf(0, 0, id(my_font), "Text to follow: %s", id(template_text).state.c_str()); it.printf(0, 0, id(my_font), "Text to follow: %s", id(template_text).state.c_str());
When using anti-aliased fonts you will probably need to specify the color to draw the characters, and the background
color to mix in for anti-aliasing. This requires the full version of `printf`, e.g.:
.. code-block:: yaml
display:
- platform: ...
# ...
lambda: |-
it.printf(10, 100, id(roboto), Color(0x123456), COLOR_OFF, display::TextAlign::BASELINE, "%f", id(heap_free).state);
The last printf tip for use in displays I will discuss here is how to display binary sensor values. You The last printf tip for use in displays I will discuss here is how to display binary sensor values. You
*could* of course just check the state with an ``if`` statement as the first few lines in the example below, but if *could* of course just check the state with an ``if`` statement as the first few lines in the example below, but if
you want to be efficient you can use an *inline if* too. With the ``%s`` print specifier you can tell it to you want to be efficient you can use an *inline if* too. With the ``%s`` print specifier you can tell it to
@ -411,14 +338,14 @@ use any string you pass it, like ``"ON"`` or ``"OFF"``.
.. _display-strftime: .. _display-strftime:
Displaying Time Displaying Time
*************** ---------------
You can display current time using a time component. Please see the example :ref:`here <strftime>`. You can display current time using a time component. Please see the example :ref:`here <strftime>`.
.. _clipping: .. _clipping:
Screen Clipping Screen Clipping
*************** ---------------
Screen clipping is a new set of methods since version 2023.2.0 of esphome. It could be useful when you just want to show Screen clipping is a new set of methods since version 2023.2.0 of esphome. It could be useful when you just want to show
a part of an image or make sure that what you draw on the screen does not go outside a specific region on the screen. a part of an image or make sure that what you draw on the screen does not go outside a specific region on the screen.
@ -470,12 +397,10 @@ With ``get_clipping();`` you get a ``Rect`` object back with the latest set clip
With ``is_clipping();`` tells you if clipping is activated. With ``is_clipping();`` tells you if clipping is activated.
.. _config-color: .. _config-color:
Color Color
***** -----
When using RGB-capable displays in ESPHome you may wish to use custom colors. When using RGB-capable displays in ESPHome you may wish to use custom colors.
A ``color`` component exists for just this purpose: A ``color`` component exists for just this purpose:
@ -525,7 +450,7 @@ RGB displays use red, green, and blue, while grayscale displays may use white.
.. _display-graphs: .. _display-graphs:
Graph Component Graph Component
*************** ---------------
You can display a graph of a sensor value(s) using this component. The states used for the graph are stored in You can display a graph of a sensor value(s) using this component. The states used for the graph are stored in
memory at the time the sensor updates and will be lost when the device reboots. memory at the time the sensor updates and will be lost when the device reboots.
@ -638,8 +563,11 @@ And then later in code:
- Axis labels are currently not possible without manually placing them. - Axis labels are currently not possible without manually placing them.
- The grid and border color is set with it.graph(), while the traces are defined separately. - The grid and border color is set with it.graph(), while the traces are defined separately.
.. _display-qrcode:
QR Code Component QR Code Component
***************** -----------------
Use this component to generate a QR-code containing a string on the device, which can then be drawn on compatible displays. Use this component to generate a QR-code containing a string on the device, which can then be drawn on compatible displays.
@ -674,8 +602,11 @@ To draw the QR-code, call the ``it.qr_code`` function from your render lambda:
// Draw the QR-code at position [x=50,y=0] with white color and a 2x scale // Draw the QR-code at position [x=50,y=0] with white color and a 2x scale
it.qr_code(50, 0, id(homepage_qr), Color(255,255,255), 2); it.qr_code(50, 0, id(homepage_qr), Color(255,255,255), 2);
.. _display-image:
Images Images
****** ------
Use this component to store graphical images on the device, you can then draw the images on compatible displays. Use this component to store graphical images on the device, you can then draw the images on compatible displays.
@ -790,7 +721,7 @@ You can also use this to invert images in two colors display, use ``COLOR_OFF``
as the additional parameters. as the additional parameters.
Animation Animation
********* ---------
Allows to use animated images on displays. Animation inherits all options from the image component. Allows to use animated images on displays. Animation inherits all options from the image component.
It adds additional lambda methods: ``next_frame()``, ``prev_frame()`` and ``set_frame()`` to change the shown picture of a gif. It adds additional lambda methods: ``next_frame()``, ``prev_frame()`` and ``set_frame()`` to change the shown picture of a gif.
@ -991,7 +922,7 @@ Troubleshooting
--------------- ---------------
Color Test Pattern Color Test Pattern
****************** ------------------
If you're experiencing issues with your color display, the script below can help you to identify what might be wrong. If you're experiencing issues with your color display, the script below can help you to identify what might be wrong.
It will show 3 color bars in **RED**, **GREEN** and **BLUE**. To help the graphics display team determine It will show 3 color bars in **RED**, **GREEN** and **BLUE**. To help the graphics display team determine
@ -1038,6 +969,7 @@ See Also
-------- --------
- :apiref:`display/display_buffer.h` - :apiref:`display/display_buffer.h`
- :ref:`Fonts <display-fonts>`
- :ghedit:`Edit` - :ghedit:`Edit`
.. toctree:: .. toctree::

1
images/format-font.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17,8H20V20H21V21H17V20H18V17H14L12.5,20H14V21H10V20H11L17,8M18,9L14.5,16H18V9M5,3H10C11.11,3 12,3.89 12,5V16H9V11H6V16H3V5C3,3.89 3.89,3 5,3M6,5V9H9V5H6Z" /></svg>

After

Width:  |  Height:  |  Size: 233 B

View File

@ -656,6 +656,7 @@ Display Components
.. imgtable:: .. imgtable::
Display Core, components/display/index, folder-open.svg, dark-invert Display Core, components/display/index, folder-open.svg, dark-invert
Font Renderer, components/display/fonts, format-font.svg, dark-invert
Addressable Light, components/display/addressable_light, addressable_light.jpg Addressable Light, components/display/addressable_light, addressable_light.jpg
ILI9xxx, components/display/ili9xxx, ili9341.jpg ILI9xxx, components/display/ili9xxx, ili9341.jpg
ILI9341, components/display/ili9xxx, ili9341.svg ILI9341, components/display/ili9xxx, ili9341.svg