Fonts

Gameface supports TrueType/OpenType fonts and collections (.ttf/.ttc/.otf/.otc). @font-face declarations in CSS are the recommended way of loading and using fonts. In order to use fonts in the frontend, you need to set them up first

Differences from the HTML Standard

A major difference from the HTML Standard is that fonts are global to the whole system and not unloaded after changing pages. This means that @font-face loaded from one View can be used in another View. A @font-face from one page can affect the next page that is loaded after following a link or changing the URL. Registered fonts are kept loaded and cannot be overwritten. Subsequent @font-face declarations matching the font description of a previously registered font will be ignored. We are keeping the fonts alive because it is common behavior in games to use the same fonts across multiple pages and this avoids loading and unloading the same font.

Another difference is that the load event is fired after fonts are loaded. We feel that this makes more sense for games instead of marking a page as loaded with various fallback fonts and font styles which will be substituted later on.

Font preloading

Unity3D doesn’t support partial reads, which means that the raw font data will always be loaded in memory to be used when needed. Be careful with the size of the fonts you use. You should place all the fonts you want to use in a Fonts folder located in any Resources folder inside the Assets folder of your project and change the file extension of each font to “.bytes”. This is necessary so that when Gameface is initialized all fonts will be loaded in memory via the Unity3D Resources.LoadAll API.

You can register fonts from C# using the cohtml.Net.IUISystem.RegisterFont API call. It works similar to the @font-face declaration. Additionally, the API allows using the original font name and styles when font description isn’t provided, unlike @font-face which is always explicit. The RegisterFont API also supports loading all fonts from a font collection when a font description isn’t provided. Providing a font description when loading a font collection will load only the first font from the collection similar to @font-face.

Register font on the default system:

CohtmlUISystem.GetDefaultUISystem().SystemNative.RegisterFont("coui://UIResources/Fonts/Oliver-Regular.ttf");

Register font on a custom system:

CohtmlUISystem systemComponent;
void Start()
{
    systemComponent = GetComponent<CohtmlUISystem>();
    systemComponent.SystemNative.RegisterFont("coui://UIResources/Fonts/Oliver-Regular.ttf");
}

Default font

The family name that was passed in the library parameter cohtml.LibraryParams.DefaultStyleFontFamily on initialize will be used when font-family for an element isn’t specified.

Font family fallback

Cohtml supports font-family fallback per character. You can specify multiple font families to be used for a single element, for example 'Droid Sans', 'Noto Sans CJK', Emoji. All characters available in Droid Sans will be used first, then for any missing character in Droid Sans, Noto Sans CJK will be used and so on.

Font weight fallback

Cohtml supports font-weight fallback per font-family and will try to select an available weight that is closest to the requested one within the same font-family. Font-family match has higher precedence than font-weight. For example, if you have Droid Sans registered as a Regular style font and you have an element that should render text as bold which uses font families Droid Sans, Noto Sans Bold, Gameface will pick Droid Sans and will draw the text with Regular font style, instead of drawing it bold with Noto Sans

Font style fallback

Cohtml doesn’t support font-style fallback yet, so styles like Italic and Oblique should be specified explicitly in order for a font match to occur. Cohtml won’t match fonts with the same font-family name and different styles.

Generic Font Families

Cohtml doesn’t support generic font families functionality, but recognizes those keywords (serif, sans-serif, monospace) in a font-family declaration and uses a specified font-family instead. The font-family that is going to be used can be configured when initializing the system with the cohtml.SystemSettings.GenericFontFamilyNameFont option. By default, Gameface will use the default font for generic font families.

Additional font fallbacks

Cohtml allows to specify additional fallback font families using cohtml::View::SetAdditionalFontFallbacks. It works as if the specified families from C++ are appended at the back of the font families defined in a stylesheet.

Last resort font fallback

Cohtml embeds a minimal font as a last resort fallback. This font was added mainly to help developers with their font setup. The visualization of this font is configurable by passing different modes to cohtml::SystemSettings::LastResortFontMode. By default, Gameface will render ASCII printable characters from the last resort font when no other suitable font is found and a square symbol for unresolved Unicode characters. The default option is suitable for visualizing simple texts without loading any fonts. cohtml::Fonts::FM_Squares will render squares for all characters for which a suitable font was not found. FM_None will disable the last resort font visualization.

Font rendering

Cohtml uses single-channel SDF (signed distance fields) to render fonts in order to achieve high performance while keeping memory consumption relatively low. However, there are some drawbacks to this method. The first is a loss of fine details in the font glyphs - this is rarely visible when using common fonts, but can be a huge problem for artistic fonts that have fine lines, dots and specks. The second drawback is rounding of sharp corners which usually can be seen only at very large font sizes and when using strokes. In some cases, the rounding of the stroke may be the desired effect.

Both issues can be significantly reduced by using multi-channel SDF. We have added support for rendering with multi-channel SDF, however since multi-channel SDF generation is expensive, Gameface doesn’t support doing it at runtime and requires the user to preload pre-generated MSDF atlases. More info on MSDF is in the next sections below.

When MSDF is not an option for mitigating the issues with either loss of detail or corner rounding, Gameface extends the @font-face declaration with a custom CSS property coh-font-sdf that can control which fonts to use SDF and which to be rasterized directly. The C++ API cohtml::System::RegisterFont also allows control over the font rendering method.

Example of how to turn off SDF:

@font-face {
  font-family: 'ExampleName';
  src: url('ExampleName.otf');
  coh-font-sdf: off;
}

Please keep in mind that stroke is only supported with SDF rendering, hence you cannot turn off SDF for stroked text.

Font fit auto-sizing

Font fit mode

Cohtml supports a custom CSS property coh-font-fit-mode. The property can be used to auto-fit text within an element, no matter the length of the text. Designers can fix the size they want on the container of the text and through coh-font-fit-mode make sure that any text put within will fit perfectly - even when the text is not yet known. The property will change the font size used to fit the text. It’s particularly handy when doing internationalization and different length texts have to fit in the same designed container.

The coh-font-fit-mode property has three possible values:

ValueEffect
noneDefault - no changes to the font size will be attempted
fitThe text font size will be changed to fit its parent - grow or shrink
shrinkThe text will shrink only its size if it can’t fit in the container

You can see an example of the property in the Localization sample.

Font fit min and max sizes

The coh-font-fit-in-size and coh-font-fit-max-size custom CSS properties can be used to set the minimum and maximum font sizes used to fit the text. This can come in handy when trying to resize text inside a container while also making sure that the text is big enough to be legible.

The coh-font-fit-in-size and coh-font-fit-max-size properties have the following effects:

PropertyDefault ValueEffect
coh‑font‑fit‑min‑size6pxDetermines the minimum font size used to fit a text if coh-font-fit-mode is not set to none. Has a minimum effective value of 6px. Any less than that will be treated by the font fitting algorithm as if coh‑font‑fit‑min‑size was set to 6px
coh‑font‑fit‑max‑size128pxDetermines the maximum font size used to fit a text if coh-font-fit-mode is set to fit. Has no effect if coh-font-fit-mode is not set to fit

If coh‑font‑fit‑max‑size is not explicitly set and the default value of 128px is used to fit the text, a warning message will be sent. To avoid this, explicitly set the coh-font-fit-max-size value.

The font fitting algorithm only works with a font size of 6px or more and a text won’t be fit with a size less than 6px, regardless of the size of the container or the coh-font-fit-min-size property.

If coh-font-fit-mode is set to fit and coh-font-fit-max-size is less than coh-font-fit-min-size, then the text’s font size will be set to that of coh-font-fit-min-size. For example, if coh-font-fit-min-size is set to 32px and coh-font-fit-max-size is set to 16px, then the text will be resized with a font size of 32px. In other words, coh-font-fit-min-size takes precedence over coh-font-fit-max-size.

Font fit shorthand

The coh-font-fit custom CSS shorthand property can be used to set coh-font-fit-mode, coh-font-fit-min-size and coh-font-fit-max-size properties together. It accepts values in the following formats:

Format
<coh-font-fit-mode>
<coh-font-fit-mode> <coh-font-fit-min-size>
<coh-font-fit-min-size> <coh-font-fit-max-size>
<coh-font-fit-mode> <coh-font-fit-min-size> <coh-font-fit-max-size>

Note that setting only the min and max sizes will result in coh-font-fit-mode being set to fit.