Magnum::Text::AbstractFont class

Base for font plugins.

Provides interface for opening fonts, filling glyph cache and layouting the glyphs.

Usage

Fonts are most commonly implemented as plugins. For example, loading a font from the filesystem using the StbTrueTypeFont plugin and prerendering all needed glyphs can be done like this, completely with all error handling:

PluginManager::Manager<Text::AbstractFont> manager;
Containers::Pointer<Text::AbstractFont> font =
    manager.loadAndInstantiate("StbTrueTypeFont");
if(!font || !font->openFile("font.ttf", 16.0f))
    Fatal{} << "Can't open font.ttf with StbTrueTypeFont";

Text::GlyphCache cache{Vector2i{512}};
font->fillGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz"
                            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                            "0123456789?!:;,. ");

See Loading and using plugins for more information about general plugin usage and *Font classes in the Text namespace for available font plugins. See GlyphCache for more information about glyph caches and Renderer for information about actual text rendering.

Loading data from memory, using file callbacks

Besides loading data directly from the filesystem using openFile() like shown above, it's possible to use openData() to import data from memory. Note that the particular importer implementation must support Feature::OpenData for this method to work.

Some font formats consist of more than one file and in that case you may want to intercept those references and load them in a custom way as well. For font plugins that advertise support for this with Feature::FileCallback this is done by specifying a file loading callback using setFileCallback(). The callback gets a filename, InputFileCallbackPolicy and an user pointer as parameters; returns a non-owning view on the loaded data or a Containers::NullOpt to indicate the file loading failed. For example, loading a memory-mapped font could look like below. Note that the file loading callback affects openFile() as well — you don't have to load the top-level file manually and pass it to openData(), any font plugin supporting the callback feature handles that correctly.

struct Data {
    std::unordered_map<std::string,
        Containers::Array<const char, Utility::Directory::MapDeleter>> files;
} data;

font->setFileCallback([](const std::string& filename,
    InputFileCallbackPolicy policy, Data& data)
        -> Containers::Optional<Containers::ArrayView<const char>>
    {
        auto found = data.files.find(filename);

        /* Discard the memory mapping, if not needed anymore */
        if(policy == InputFileCallbackPolicy::Close) {
            if(found != data.files.end()) data.files.erase(found);
            return {};
        }

        /* Load if not there yet */
        if(found == data.files.end()) found = data.files.emplace(
            filename, Utility::Directory::mapRead(filename)).first;

        return Containers::arrayView(found->second);
    }, data);

font->openFile("magnum-font.conf", 13.0f);

For importers that don't support Feature::FileCallback directly, the base openFile() implementation will use the file callback to pass the loaded data through to openData(), in case the importer supports at least Feature::OpenData. If the importer supports neither Feature::FileCallback nor Feature::OpenData, setFileCallback() doesn't allow the callbacks to be set.

The input file callback signature is the same for Text::AbstractFont and Trade::AbstractImporter to allow code reuse.

Subclassing

The plugin implements doFeatures(), doClose(), doLayout(), either doCreateGlyphCache() or doFillGlyphCache() and one or more of doOpen*() functions. See also AbstractLayouter for more information.

You don't need to do most of the redundant sanity checks, these things are checked by the implementation:

Derived classes

class FreeTypeFont
FreeType font plugin.
class MagnumFont
Simple bitmap font plugin.
class StbTrueTypeFont
TrueType font plugin using stb_truetype.

Public types

enum class Feature: UnsignedByte { OpenData = 1 << 0, FileCallback = 1 << 1 new in 2019.10, MultiFile = FileCallback deprecated in 2019.10, PreparedGlyphCache = 1 << 2 }
Features supported by this font implementation.
using Features = Containers::EnumSet<Feature>
Set of features supported by this font implementation.

Public static functions

static auto pluginInterface() -> std::string
Plugin interface.
static auto pluginSearchPaths() -> std::vector<std::string>
Plugin search paths.

Constructors, destructors, conversion operators

AbstractFont() explicit
Default constructor.
AbstractFont(PluginManager::AbstractManager& manager, const std::string& plugin) explicit
Plugin manager constructor.

Public functions

auto features() const -> Features
Features supported by this font.
auto fileCallback() -> auto new in 2019.10
File opening callback function.
auto fileCallbackUserData() const -> void* new in 2019.10
File opening callback user data.
void setFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, void*) callback, void* userData = nullptr) new in 2019.10
Set file opening callback.
template<class T>
void setFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, T&) callback, T& userData) new in 2019.10
Set file opening callback.
auto isOpened() const -> bool
Whether any file is opened.
auto openData(Containers::ArrayView<const char> data, Float size) -> bool
Open font from raw data.
auto openData(const std::vector<std::pair<std::string, Containers::ArrayView<const char>>>& data, Float size) -> bool deprecated in 2019.10
Open font from raw data.
auto openSingleData(Containers::ArrayView<const char> data, Float size) -> bool deprecated in 2019.10
Open font from raw data.
auto openFile(const std::string& filename, Float size) -> bool
Open font from file.
void close()
Close font.
auto size() const -> Float
Font size.
auto ascent() const -> Float
Font ascent.
auto descent() const -> Float
Font descent.
auto lineHeight() const -> Float
Line height.
auto glyphId(char32_t character) -> UnsignedInt
Glyph ID for given character.
auto glyphAdvance(UnsignedInt glyph) -> Vector2
Glyph advance.
void fillGlyphCache(AbstractGlyphCache& cache, const std::string& characters)
Fill glyph cache with given character set.
auto createGlyphCache() -> Containers::Pointer<AbstractGlyphCache>
Create glyph cache.
auto layout(const AbstractGlyphCache& cache, Float size, const std::string& text) -> Containers::Pointer<AbstractLayouter>
Layout the text using font's own layouter.

Protected types

struct Metrics
Font metrics.

Protected functions

auto doOpenFile(const std::string& filename, Float size) -> Metrics virtual
Implementation for openFile()

Private functions

auto doFeatures() const -> Features pure virtual
Implementation for features()
void doSetFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, void*) callback, void* userData) virtual
Implementation for setFileCallback()
auto doIsOpened() const -> bool pure virtual
Implementation for isOpened()
auto doOpenData(Containers::ArrayView<const char> data, Float size) -> Metrics virtual
Implementation for openData()
void doClose() pure virtual
Implementation for close()
auto doGlyphId(char32_t character) -> UnsignedInt pure virtual
Implementation for glyphId()
auto doGlyphAdvance(UnsignedInt glyph) -> Vector2 pure virtual
Implementation for glyphAdvance()
void doFillGlyphCache(AbstractGlyphCache& cache, const std::u32string& characters) virtual
Implementation for fillGlyphCache()
auto doCreateGlyphCache() -> Containers::Pointer<AbstractGlyphCache> virtual
Implementation for createGlyphCache()
auto doLayout(const AbstractGlyphCache& cache, Float size, const std::string& text) -> Containers::Pointer<AbstractLayouter> pure virtual
Implementation for layout()

Enum documentation

enum class Magnum::Text::AbstractFont::Feature: UnsignedByte

Features supported by this font implementation.

Enumerators
OpenData

Opening fonts from raw data using openData()

FileCallback new in 2019.10

Specifying callbacks for loading additional files referenced from the main file using setFileCallback(). If the font doesn't expose this feature, the format is either single-file or loading via callbacks is not supported.

See Loading data from memory, using file callbacks and particular font plugin documentation for more information.

MultiFile

The format is multi-file, thus openSingleData() convenience function cannot be used.

PreparedGlyphCache

The font contains prepared glyph cache.

Function documentation

static std::string Magnum::Text::AbstractFont::pluginInterface()

Plugin interface.

"cz.mosra.magnum.Text.AbstractFont/0.3"

static std::vector<std::string> Magnum::Text::AbstractFont::pluginSearchPaths()

Plugin search paths.

First looks in magnum/fonts/ or magnum-d/fonts/ next to the executable (or, in case of Windows and a non-static build, next to the DLL of the Text library) and as a fallback in magnum/fonts/ or magnum-d/fonts/ in the runtime install location (lib[64]/ on Unix-like systems, bin/ on Windows). The system-wide plugin search directory is configurable using the MAGNUM_PLUGINS_DIR CMake variables, see Downloading and building for more information.

Not defined on platforms without dynamic plugin support.

auto Magnum::Text::AbstractFont::fileCallback() new in 2019.10

File opening callback function.

void* Magnum::Text::AbstractFont::fileCallbackUserData() const new in 2019.10

File opening callback user data.

void Magnum::Text::AbstractFont::setFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, void*) callback, void* userData = nullptr) new in 2019.10

Set file opening callback.

In case the font plugin supports Feature::FileCallback, files opened through openFile() will be loaded through the provided callback. Besides that, all external files referenced by the top-level file will be loaded through the callback function as well, usually on demand. The callback function gets a filename, InputFileCallbackPolicy and the userData pointer as input and returns a non-owning view on the loaded data as output or a Corrade::Containers::NullOpt if loading failed — because empty files might also be valid in some circumstances, nullptr can't be used to indicate a failure.

In case the font plugin doesn't support Feature::FileCallback but supports at least Feature::OpenData, a file opened through openFile() will be internally loaded through the provided callback and then passed to openData(). First the file is loaded with InputFileCallbackPolicy::LoadTemporary passed to the callback, then the returned memory view is passed to openData() (sidestepping the potential openFile() implementation of that particular font plugin) and after that the callback is called again with InputFileCallbackPolicy::Close because the semantics of openData() don't require the data to be alive after. In case you need a different behavior, use openData() directly.

In case callback is nullptr, the current callback (if any) is reset. This function expects that the font plugin supports either Feature::FileCallback or Feature::OpenData. If an font plugin supports neither, callbacks can't be used.

It's expected that this function is called before a file is opened. It's also expected that the loaded data are kept in scope for as long as the font plugin needs them, based on the value of InputFileCallbackPolicy. Documentation of particular importers provides more information about the expected callback behavior.

Following is an example of setting up a file loading callback for fetching compiled-in resources from Corrade::Utility::Resource. See the overload below for a more convenient type-safe way to pass the user data pointer.

font->setFileCallback([](const std::string& filename,
    InputFileCallbackPolicy, void*) {
        Utility::Resource rs("data");
        return Containers::optional(rs.getRaw(filename));
    });

template<class T>
void Magnum::Text::AbstractFont::setFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, T&) callback, T& userData) new in 2019.10

Set file opening callback.

Equivalent to calling the above with a lambda wrapper that casts void* back to T* and dereferences it in order to pass it to callback. Example usage:

struct Data {
    std::unordered_map<std::string, Containers::Array<char>> files;
} data;

font->setFileCallback([](const std::string& filename,
    InputFileCallbackPolicy, Data& data)
        -> Containers::Optional<Containers::ArrayView<const char>>
    {
        auto found = data.files.find(filename);
        if(found == data.files.end()) {
            if(!Utility::Directory::exists(filename))
                return Containers::NullOpt;
            found = data.files.emplace(filename, Utility::Directory::read(filename)).first;
        }
        return Containers::ArrayView<const char>{found->second};
    }, data);

bool Magnum::Text::AbstractFont::openData(Containers::ArrayView<const char> data, Float size)

Open font from raw data.

Parameters
data File data
size Font size

Closes previous file, if it was opened, and tries to open given file. Available only if Feature::OpenData is supported. Returns true on success, false otherwise.

bool Magnum::Text::AbstractFont::openData(const std::vector<std::pair<std::string, Containers::ArrayView<const char>>>& data, Float size)

Open font from raw data.

bool Magnum::Text::AbstractFont::openSingleData(Containers::ArrayView<const char> data, Float size)

Open font from raw data.

bool Magnum::Text::AbstractFont::openFile(const std::string& filename, Float size)

Open font from file.

Parameters
filename Font file
size Font size

Closes previous file, if it was opened, and tries to open given file. If the plugin has Feature::MultiFile, the function will use additional files in given path, all sharing common basename derived from filename. Returns true on success, false otherwise.

Float Magnum::Text::AbstractFont::size() const

Font size.

Returns scale in which lineHeight(), ascent(), descent() and glyphAdvance() is returned. Expects that a font is opened.

Float Magnum::Text::AbstractFont::ascent() const

Font ascent.

Distance from baseline to top, scaled to font size. Positive value. Expects that a font is opened.

Float Magnum::Text::AbstractFont::descent() const

Font descent.

Distance from baseline to bottom, scalled to font size. Negative value. Expects that a font is opened.

Float Magnum::Text::AbstractFont::lineHeight() const

Line height.

Returns line height scaled to font size. Expects that a font is opened.

UnsignedInt Magnum::Text::AbstractFont::glyphId(char32_t character)

Glyph ID for given character.

Expects that a font is opened.

Vector2 Magnum::Text::AbstractFont::glyphAdvance(UnsignedInt glyph)

Glyph advance.

Parameters
glyph Glyph ID

Returns glyph advance scaled to font size. Expects that a font is opened.

void Magnum::Text::AbstractFont::fillGlyphCache(AbstractGlyphCache& cache, const std::string& characters)

Fill glyph cache with given character set.

Parameters
cache Glyph cache instance
characters UTF-8 characters to render

Fills the cache with given characters. Fonts having Feature::PreparedGlyphCache do not support partial glyph cache filling, use createGlyphCache() instead. Expects that a font is opened.

Containers::Pointer<AbstractGlyphCache> Magnum::Text::AbstractFont::createGlyphCache()

Create glyph cache.

Configures and fills glyph cache with the contents of whole font. Available only if Feature::PreparedGlyphCache is supported. Other fonts support only partial glyph cache filling, see fillGlyphCache(). Expects that a font is opened.

Containers::Pointer<AbstractLayouter> Magnum::Text::AbstractFont::layout(const AbstractGlyphCache& cache, Float size, const std::string& text)

Layout the text using font's own layouter.

Parameters
cache Glyph cache
size Font size
text Text to layout

Note that the layouters support rendering of single-line text only. See Renderer class for more advanced text layouting. Expects that a font is opened.

Metrics Magnum::Text::AbstractFont::doOpenFile(const std::string& filename, Float size) virtual protected

Implementation for openFile()

Return metrics of opened font on successful opening, zeros otherwise. If Feature::OpenData is supported, default implementation opens the file and calls doOpenData() with its contents. It is allowed to call this function from your doOpenFile() implementation — in particular, this implementation will also correctly handle callbacks set through setFileCallback().

This function is not called when file callbacks are set through setFileCallback() and Feature::FileCallback is not supported — instead, file is loaded though the callback and data passed through to doOpenData().

void Magnum::Text::AbstractFont::doSetFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, void*) callback, void* userData) virtual private

Implementation for setFileCallback()

Useful when the font plugin needs to modify some internal state on callback setup. Default implementation does nothing and this function doesn't need to be implemented — the callback function and user data pointer are available through fileCallback() and fileCallbackUserData().

Metrics Magnum::Text::AbstractFont::doOpenData(Containers::ArrayView<const char> data, Float size) virtual private

Implementation for openData()

Return metrics of opened font on successful opening, zeros otherwise.

void Magnum::Text::AbstractFont::doFillGlyphCache(AbstractGlyphCache& cache, const std::u32string& characters) virtual private

Implementation for fillGlyphCache()

The string is converted from UTF-8 to UTF-32, unique characters are not removed.

Debug& operator<<(Debug& debug, AbstractFont::Feature value)

Debug output operator.

Debug& operator<<(Debug& debug, AbstractFont::Features value)

Debug output operator.