Cross-platform C SDK logo

Cross-platform C SDK

Fonts

❮ Back
Next ❯

Functions

Font*font_create (...)
Font*font_system (...)
Font*font_monospace (...)
Font*font_with_style (...)
Font*font_with_width (...)
Font*font_with_xscale (...)
Font*font_copy (...)
voidfont_destroy (...)
bool_tfont_equals (...)
real32_tfont_regular_size (void)
real32_tfont_small_size (void)
real32_tfont_mini_size (void)
const char_t*font_family (...)
real32_tfont_size (...)
real32_tfont_height (...)
real32_tfont_width (...)
real32_tfont_xscale (...)
real32_tfont_ascent (...)
real32_tfont_descent (...)
real32_tfont_leading (...)
bool_tfont_is_monospace (...)
uint32_tfont_style (...)
voidfont_extents (...)
bool_tfont_exists_family (...)
ArrPt(String)*font_installed_families (void)
ArrPt(String)*font_installed_monospace (void)
void*font_native (...)

Fonts are graphic objects (files) that contain the characters and symbols that we see on a monitor. We remember that a Unicode string only stores the code of the characters (codepoints) without any information about how they will be drawn. The graphic associated with a character is known as a glyph and, in a font file, there are as many glyphs as codepoints can represent the typography. The pairing between codepoints and their corresponding glyphs is carried out by the graphics subsystem of the operating system (Listing 1) (Figure 1).

Listing 1: Drawing of a text string.
1
2
3
4
Font *font = font_create("Comic Sans MS" 28, 0);
draw_font(ctx, font);
draw_text(ctx, "Hello World", 200, 250);
font_destroy(&font);
Graphic that relates Unicode characters to glyphs and fonts.
Figure 1: Text representation: codepoints + glyphs.

1. Create fonts

When displaying texts in graphical interfaces it is necessary to establish a typography, otherwise the system would not know how to render it. There will always be a font defined by default, but we can change it when customizing the appearance of our texts.

The most representative characteristic of a font's design is the family to which it belongs (font family or typeface) (Figure 2). Each computer has a series of families installed that do not have to coincide with those incorporated in another machine. This is an important fact to take into account since, for the sake of portability, we should not assume that a certain font family will be present on all the machines that run the program. Sentences of the type:

1
Font *font = font_create("Comic Sans MS", 28, 0);

will not be completely portable, since we are not sure that the Comic Sans MS font is installed on all computers.

  • Use font_installed_families to get the list of all families installed on the machine.
  • Hello World text written using different typography.
    Figure 2: Different font families.

2. System font

There is always a default font associated with the window environment and that, in a certain way, gives it part of its personality. Using this font guarantees the correct integration of our program in all the systems where it is executed, making our code totally portable (Figure 3). Controls such as Button or Label have the system font associated with a regular size by default. The best known are:

  • Segoe UI: Windows Vista, 7, 8, 10, 11.
  • Tahoma: Windows XP.
  • San Francisco: Mac OSX El Capitan and later.
  • Helvetica Neue: Mac OSX Yosemite.
  • Lucida Grande: Mac OSX Mavericks, Mountain Lion, Lion, Snow Leopard.
  • Ubuntu: Linux Ubuntu.
  • Piboto: Linux Raspbian.
  • Cantarell: Kali Linux.
  • Capture the same application on different systems, using the default font.
    Figure 3: Using system font.

3. Monospace font

In addition to the system font we have another monospaced font available by default (Figure 4). These fonts imitate old typewriters, where all the characters occupy the same space. They are usually used for technical documents or source code files.

In general, graphics APIs do not offer a monospace font by default. NAppGUI will select the most appropriate one in each case by searching among the installed fonts:

  • Windows: Consolas, Courier New.
  • macOS: SF Mono, Menlo, Monaco, Andale Mono, Courier New.
  • Linux: Ubuntu Mono, DejaVu Sans Mono, Courier New.
Starting with macOS Catalina, Cocoa does offer a monospace system font.

However, you can register a default monospace family for the entire application using draw2d_preferred_monospace. Any call to font_monospace will give priority to this user option.


4. Font style

In addition to the family, we will have certain properties (style) that will also influence its appearance. They are grouped in the style parameter of the constructor, combining the values of fstyle_t (Figure 5).


5. Size and metrics

Although the font size (size) is the only metric that we can configure when creating a font, there are different associated measurements that can be useful when working with vector graphics (Figure 6). The most used will be the line height (height), in general, somewhat larger than the font size since it includes a small vertical margin (leading). You can use the constant ekFCELL in style to indicate that size refers to line height instead of letter height.

Graphic with the different measurements of a text.
Figure 6: Text metrics with a given font.

5.1. Size in points

By default, the font size is expressed in pixels, but it can be changed by adding ekFPOINTS to the style parameter. This unit is related to printed sources on paper. Here the concept of DPI (dots per inch) appears, which indicates the number of isolated ink droplets that a printing device can emit per metric inch. In typography the criterion of 72 DPI is established, therefore, the size of a point is approximately 0.35mm. This way it is easy to calculate the font size from the points: 12pt=4.2mm, 36pt=12.7mm or 72pt=25.4mm (1 inch). This is the unit used in word processors, which already work based on a print page size. The problem arises when we want to represent fonts expressed in points on a screen, since there is no exact correspondence between pixels and millimeters. The final pixel size depends on the resolution and the physical size of the monitor. A conversion agreement is required between pixels and inches, which gives rise to the term PPI (pixels per inch). Traditionally, Windows systems are set at 96 PPI while on Apple iMacs it is 72 PPI. This causes fonts expressed in points to be 33% larger in Windows (Figure 7). Furthermore, in the Microsoft system it is possible to configure the PPI by the user, which adds more uncertainty about the final size of the texts on the screen.

Comparison between size in pixels and size in points.
Figure 7: The ekFPOINTS unit is not recommended for screens.

6. Font stretch

In general, the average character width is determined by the font size and we should almost never need to change (Figure 8). But sometimes it can be useful to "stretch" or "collapse" the text while leaving its height intact. Let's think, for example, about the emulation of terminals where each cell must occupy a certain width.

Different GUI elements where the font width has been changed.
Figure 8: Effect of changing font width on drawing contexts and GUI elements.

We consider average width to be the size in pixels of the string [A-Z][a-z][0-9] divided by 62. Obviously, in monospaced fonts, the average width will correspond to the width of any character. Scaling in X is a value related to the width, but more intuitive when creating the font.


7. Bitmap and Outline fonts

In early computers, fonts were created as raster graphics Bitmap Fonts (Figure 9). Each character fit into a cell of fixed size where those pixels that composed it were marked. The biggest problem is that they don't scale well. As we make the text on the screen larger, the jagged effect of the pixels becomes evident.

Enlargement of a bitmap font, where the jagged effect can be seen.
Figure 9: Bitmap fonts.

In 1982 Adobe launched the PostScript format that included what were known as Outline Fonts (Figure 10). This format contains a geometric description of each symbol based on lines and Bezier curves. In this way, the pixelated effect of the bitmap is avoided, since when the character is scaled, the pixels that make it up are re-computed in a process known as rasterization. At the end of the 80's Apple launched the TrueType format and sold a license to Microsoft that incorporated it in Windows 3.1, opening the door to the mass market for vector fonts. Nowadays all systems work with scalable fonts, with TrueType and OpenType being the clearest representatives.

Scaling of an outline font (vector).
Figure 10: Outline fonts, on which the TrueType and OpenType formats are based.

8. Unicode and glyphs

Unicode is a very extensive table. In version 11 (June 2018) there are 137,374 codepoints registered and this number grows with each new revision of the standard. If the application requires special symbols (above BMP-Basic Multilingual Plane) we must make sure that the selected fonts contain glyphs for them. To see the relationship between codepoints and glyphs we can use the BabelMap (Figure 11) application, and within it the Font Analysis option. Starting from a Unicode block, it will show those installed fonts that include glyphs for that range. In macOS we have a similar application called Character Viewer and in Ubuntu another called Character Map.

Application that shows the glyphs included in each font.
Figure 11: BabelMap Font Analysis provides us with information about the glyphs included in each font.
❮ Back
Next ❯

font_create ()

Create a font.

Font*
font_create(const char_t *family,
            const real32_t size,
            const uint32_t style);
family

Typographic family. Pe: "Arial", "Times New Roman", etc.

size

Font size. Defaults to pixels. Use ekFPOINTS in style to change the unit.

style

Operation OR | on the fields of the fstyle_t structure. Eg: ekFBOLD | ekFITALIC.

Return

The newly created font.


font_system ()

Create a font, with the system's default family.

Font*
font_system(const real32_t size,
            const uint32_t style);
size

Font size. Defaults to pixels. Use ekFPOINTS in style to change the unit.

style

Operation OR | on the fields of the fstyle_t structure. Eg: ekFBOLD | ekFITALIC.

Return

The newly created font.

Remarks

See System font.


font_monospace ()

Create a font, with the system's default monospace family.

Font*
font_monospace(const real32_t size,
               const uint32_t style);
size

Font size. Defaults to pixels. Use ekFPOINTS in style to change the unit.

style

Operation OR | on the fields of the fstyle_t structure. Eg: ekFBOLD | ekFITALIC.

Return

The newly created font.

Remarks

See Monospace font.


font_with_style ()

Create a copy of an existing font, changing the style.

Font*
font_with_style(const Font *font,
                const uint32_t style);
font

Original font.

style

Operation OR | on the fields of the fstyle_t structure. Eg: ekFBOLD | ekFITALIC.

Return

A copy of font with another style.


font_with_width ()

Creates a copy of an existing font, changing the average width of the character.

Font*
font_with_width(const Font *font,
                const real32_t width);
font

Original font.

width

Average character width.

Return

A copy of font changing the character width.

Remarks

Average width is considered the size in pixels of the string "[A-Z][a-z][0-9]" / 62. Changing this value implies changing the scaling in x, since they are related values. See Font stretch.


font_with_xscale ()

Creates a copy of an existing font, changing the x-scaling of the text.

Font*
font_with_xscale(const Font *font,
                 const real32_t scale);
font

Original font.

scale

Scaling. By default it is 1.

Return

A copy of font changing the scaling.

Remarks

Changing the scaling involves changing the average width of the character, since they are related values. See Font stretch.


font_copy ()

Creates an exact copy of a typeface.

Font*
font_copy(const Font *font);
font

Original font.

Return

The copy of font.

Remarks

Fonts are immutable objects. Copying really means incrementing an internal counter without actually cloning the object. However, the application must destroy the copy with font_destroy just like those created with any other constructor.


font_destroy ()

Destroy the font.

void
font_destroy(Font **font);
font

The font. It will be set to NULL after destruction.


font_equals ()

Compare two sources. They are considered equal if they have the same family, size and style.

bool_t
font_equals(const Font *font1,
            const Font *font2);
font1

First font to compare.

font2

Second font to compare.

Return

TRUE if they are equal, FALSE if not.


font_regular_size ()

Gets the default font size for interface controls.

real32_t
font_regular_size(void);

Return

The default size in pixels.

Remarks

See System font.


font_small_size ()

Gets the small default font size for interface controls.

real32_t
font_small_size(void);

Return

The size in pixels.

Remarks

This size is slightly smaller than that obtained by font_regular_size.


font_mini_size ()

Gets the mini default font size for interface controls.

real32_t
font_mini_size(void);

Return

The size in pixels.

Remarks

This size is slightly smaller than that obtained by font_small_size.


font_family ()

Gets the font family.

const char_t*
font_family(const Font *font);
font

The font.

Return

The font family in UTF8.


font_size ()

Gets the font size.

real32_t
font_size(const Font *font);
font

The font.

Return

The size. The units depend on the style parameter.

Remarks

See Size and metrics.


font_height ()

Gets the height of the cell or line of text with this font.

real32_t
font_height(const Font *font);
font

The font.

Return

Line height.

Remarks

See Size and metrics.


font_width ()

Gets the average width of the character.

real32_t
font_width(const Font *font);
font

The font.

Return

Average width.

Remarks

Ver Font stretch.


font_xscale ()

Gets the x scaling of the text.

real32_t
font_xscale(const Font *font);
font

The font.

Return

Scaling.

Remarks

Ver Font stretch.


font_ascent ()

Obtains the measurement of the font above the baseline.

real32_t
font_ascent(const Font *font);
font

The font.

Return

Above measurement.

Remarks

See Size and metrics.


font_descent ()

Obtains the measurement of the font below the baseline.

real32_t
font_descent(const Font *font);
font

The font.

Return

Below measurement.

Remarks

See Size and metrics.


font_leading ()

Gets the margin between the character size and the line height.

real32_t
font_leading(const Font *font);
font

The font.

Return

Margin.

Remarks

See Size and metrics.


font_is_monospace ()

Checks if a font is monospaced or not.

bool_t
font_is_monospace(const Font *font);
font

The font.

Return

TRUE if the font is monospaced.

Remarks

See Monospace font.


font_style ()

Gets the style of the font.

uint32_t
font_style(const Font *font);
font

The font.

Return

The style. Combination of values of the fstyle_t structure. Eg: ekFBOLD | ekFITALIC.


font_extents ()

Gets the size in pixels of a text string, based on the font.

void
font_extents(const Font *font,
             const char_t *text,
             const real32_t refwidth,
             real32_t *width,
             real32_t *height);
font

The font.

text

The text string to size.

refwidth

Maximum width of the text box or -1.

width

Width of the text box.

height

Height of the text box.

Remarks

If line breaks '\n' are found the text box will grow in height. Setting refwidth > 0 will limit the width of the box, growing in height enough to hold all the text. A single line of text will only be considered if refwidth < 0 and '\n' do not exist.


font_exists_family ()

Checks if a font family is installed on the operating system.

bool_t
font_exists_family(const char_t *family);
family

UTF8 string with the family name, null-terminated '\0'.

Return

TRUE if the family exists, FALSE if not.


font_installed_families ()

Gets a list of the names of all font families installed on the operating system.

ArrPt(String)*
font_installed_families(void);
1
2
3

Return

Array of String with the names of the families, ordered alphabetically. It must be destroyed with arrpt_destroy.

Remarks

See Create fonts.


font_installed_monospace ()

Gets a list of the names of all monospaced families installed on the operating system.

ArrPt(String)*
font_installed_monospace(void);
1
2
3

Return

Array of String with the names of the families, ordered alphabetically. It must be destroyed with arrpt_destroy.

Remarks

See Monospace font.


font_native ()

Gets the source in the native format of each platform.

void*
font_native(const Font *font);
font

The font.

Return

The native source. HFONT on Windows, PangoFontDescription on Linux and NSFont on macOS.

❮ Back
Next ❯