Skip to content

Most of the functionality in systemfonts is intended to be used from compiled code to help e.g. graphic devices to resolve font specifications to a font file prior to rendering. systemfonts provide key functionality to get called at the C level by putting systemfonts in the LinkingTo field in the description and adding #include <systemfonts.h> to your C code. Make sure systemfonts is loaded before using it, e.g. by having match_fonts() imported into your package namespace. All functions are provided in the systemfonts::ver2 namespace. Legacy API is not namespaced. The different functionality will be discussed below:

Font matching

The C equivalent of the match_fonts() R function is locate_font() with the following signature:

FontSettings2 locate_font(
  const char *family,
  double italic,
  double weight,
  double width,
  const int* axes,
  const int* coords,
  int n_axes
)

It takes a UTF-8 encoded string with the font family name, a double giving italic (usually 0.0 == “upright” and 1.0 == “italic”), a double giving weight (usually ranging between 100.0 and 1000.0 — 0.0 means “undefined”) and a double giving “width” (usually ranging from 1.0 to 10.0 — 0.0 means undefined). Lastly you can provide variable axis coords with the axes and coords array pointers with n_axes giving the number in the arrays (which are assumed to be of the same length). The values of each array are not immediately understandable to the human eye and will usually come from a user through a call to font_variation(). If the axes array contain “ital”, “wght”, and/or “wdth” and the font has these variable axes then the values for these axes will overwrite the values provide in italic, weight, and width.

The returned FontSettings2 struct will contain both the font location and index along with any OpenType feature settings and the axes settings in the case of a variable font. The struct (along with its FontFeature struct dependency) is shown below and is pretty self-documenting.

Do not cache the FontSettings2 struct as the features, axes, and coords arrays may be cleared at any time after the call has ended. systemfonts itself takes care of caching so this is not something you should be concerned with in your code.

struct FontFeature {
  char feature[4];
  int setting;
};
struct FontSettings {
  char file[PATH_MAX + 1];
  unsigned int index;
  const FontFeature* features;
  int n_features;
  const int* axes;
  const int* coords;
  int n_axes;
};

Glyph metrics

The C equivalent of glyph_info() is glyph_metrics() with the following signature:

int glyph_metrics(
  uint32_t code,
  const FontSettings2& font,
  double size,
  double res,
  double* ascent,
  double* descent,
  double* width
)

It takes the glyph to measure as an int giving the UTF code of the glyph, with a FontSettings2 object describing the font. Further it takes a size in pt and a resolution in ppi. It will write the ascent, descent, and width in pts to the pointers passed in, and return 0 if the operation was successful.

Retrieving cached freetype face

A heavy part of text layouting is reading and parsing font files. systemfonts contains its own cache to make sure that parsing is kept at a minimum. If you want to use this cache to load and cache freetype face object (FT_Face) you can use get_cached_face(). This resides in a separate header (systemfonts-ft.h) because it requires FreeType to be linked in your package, which the rest of the C api does not. It will look in the cache for a face and size that matches your request and return that if found. If not, it will load it for you and add it to the cache, before returning it to you. get_cached_face() sets the passed int error pointer to 0 if successful.

get_cached_face(
  const FontSettings2& font,
  double size,
  double res,
  int * error
)

Freetype uses reference counting to keep track of objects and the count is increased by a call to get_cached_face(). It is the responsibility of the caller to decrease it once the face is no longer needed using FT_Done_Face().

Font fallback

When rendering text it is not given that all the requested characters have a glyph in the given font. While one can elect to render a “missing glyph” glyph (often either an empty square or a questionmark in a tilted square) a better approach is often to find a font substitute that does contain the character and use that for rendering it. This function allows you to find a fallback font for a given string and font. The string should be stripped of characters that you already know how to render. The fallback font is returned as a FontSettings2 object, though features are always empty.

FontSettings2 get_fallback(
  const char* string,
  const FontSettings2& font
)

Font Weight

When encoding text with CSS it may be necessary to know the exact weight of the font given by a file so that it may be reflected in the style sheet. This function takes a FontSettings2 object and returns the weight (100-900 or 0 if it is undefined by the font) respecting the variable axes settings if given.

int get_font_weight(
  const FontSettings2& font
)

Family name

It may be beneficial to know the family name from a given font. This can be obtained with get_font_family() which will write the name to the provided char* argument. It will return 0 if it was somehow unsuccessful.

int get_font_family(
  const FontSettings2& font,
  char* family,
  int max_length
)

Emoji location

Figuring out which character in a string should be treated as an emoji is non-trivial due to the existence of emojis with text representation default etc. systemfonts allow you to get the embedding of emojis in a string based on the correct rules.

void detect_emoji_embedding(
  const uint32_t* string,
  int n,
  int* embedding,
  const FontSettings2& font
)