Skip to content
Philip Howard edited this page Dec 30, 2020 · 5 revisions

Text

Fonts

The 32blit engine supplies several functions for drawing text to the screen - or another surface - in any of the built-in fonts, or a ttf font via the asset pipeline.

Built-in Fonts

32blit provides three built-in fonts to get you started.

  1. Minimal Font - minimal_font
  2. Outline Font - outline_font
  3. Fat Font - fat_font

Custom Fonts

Custom fonts can be added to your game using the 32blit asset pipeline. ttf fonts are recognised and converted automatically. gif and png images are also supported, and should define individual characters in a single row with regular spacing.

TTF Fonts

Using a ttf font, such as PressStart2P-Regular.ttf, in a 32blit project requires an assets.yml defining the font source, name and desired height:

font_asset.cpp:
  PressStart2P-Regular.ttf:
    name: custom_font_data
    height: 8

This defines the filename that the asset builder should generate - font_asset.cpp, the input font PressStart2P-Regular.ttf, the name of the font asset name: custom_font_data and, finally, the height in pixels since the font is baked from ttf to a fixed size bitmap: height: 8.

PNG/GIF Fonts

A png or gif font is transformed from a png or gif image containing all the desired characters, spaced regularly in a single row.

The width of each character is determined by dividing the input image width by the number of characters it contains.

The height of each character is determined by the input image height.

Images should typically contain 96 characters, starting with ! and ending with ~, representing all printable characters in the ASCII set, though the number of characters and starting offset can be customised.

The width of a space can be defined with space_width (defaulting to 3px) and the gap between lines of text can be specified with vertical_spacing.

Variable width text is computed automatically by looking for filled pixels from left to right.

The following assets.yml will convert the input file 12x8font.png:

font_asset.cpp:
  12x8font.png:
    name: custom_font_data
    type: font/image
    vertical_spacing: 0
    space_width: 4

Using Custom Fonts

In both cases an output file of font_asset.cpp will generate two source files:

  • font_asset.hpp
  • font_asset.cpp

To process and build assets during compilation, a line must be added to CMakeLists.txt:

blit_assets_yaml (text assets.yml)

The output resource font_asset.hpp must be included in a project and a custom font defined:

#include "font_asset.hpp"

const Font custom_font(custom_font_data);

And, finally, custom_font can be used in place of the built-in fonts when drawing text:

text = "This text uses\nan imported\nTrueType font.";
screen.text(text, custom_font, Point(0, 0), true);

Drawing Text

There are two methods for drawing text, one that uses a Rect to define a bounding box, inside which text is wrapped:

void text(std::string_view message, const Font &font, const Rect &r, bool variable = true, TextAlign align = TextAlign::top_left);

And one that uses a Point defining the origin of the text, which is the top-left corner by default:

void text(std::string_view message, const Font &font, const Point &p, bool variable = true, TextAlign align = TextAlign::top_left);

Rect/Point Position

Using a Rect will specify a container for the text, explicitly defining the top, left, bottom and right edges against which it will be aligned.

A Point defines the origin of the text, and text will be aligned against this point- right-aligned text will draw on the left of the point, left-aligned text will draw on the right of the point and so on.

Fixed/Variable Width

Fixed width text ensures that every character is the same width, so the length of the rendered text is predictable. This might be used where a space for n digits (such as a two digit lives count) is reserved in the interface.

Variable width is great for readability where text does not need to fit in a specific bounding box and might wrap and scroll.

Alignment

The 5th argument to screen.text allows text alignment to be set using a 4-bit flag.

screen.text(text, minimal_font, text_rect, variable_width, TextAlign::center_center);

The following alignment options are available:

  • Left - TextAlign::left
  • Center (Horizontal) - TextAlign::center_h
  • Right - TextAlign::right
  • Top - TextAlign::top
  • Center (Vertical) - TextAlign::center_v
  • Bottom - TextAlign::bottom

There are also shorthands for valid alignment combinations:

  • Top Left - TextAlign::top_left
  • Center Left - TextAlign::center_left
  • Bottom Left - TextAlign::bottom_left
  • Top Center - TextAlign::top_center
  • Center - TextAlign::center_center
  • Bottom Center - TextAlign::bottom_center
  • Top Right - TextAlign::top_right
  • Center Right - TextAlign::center_right
  • Bottom Right - TextAlign::bottom_right

Masking/Clipping

The display clipping rectangle affects text like any other drawing operation.

Set a rectangle to screen.clip and text will not be drawn outside of this region.

Other Text Functions

Get Text Size

Knowing the width/height of text is useful for positioning. It can be obtained with measure_text which returns a Size object with w and h properties.

Size measure_text(std::string_view message, const Font &font, bool variable = true);

Wrap Text

draw_text will not wrap text if it reaches the bounds of its containing Rect. Text must be wrapped explicitly before being drawn. This is accomplished either explitly using \n or using wrap_text, which accepts broadly the same arguments as draw_text:

std::string wrap_text(std::string_view message, int32_t width, const Font &font, bool variable = true, bool words = true);

Text is wrapped to width, attempting to break at word boundaries by default. If the words argument is set to false the function will work by breaking at letter boundaries and potentially breaking words. The newline character - \n - should be used to force linebreaks where breaking words is undesired.