Fonts
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 (...) |
void | font_destroy (...) |
bool_t | font_equals (...) |
real32_t | font_regular_size (void) |
real32_t | font_small_size (void) |
real32_t | font_mini_size (void) |
const char_t* | font_family (...) |
real32_t | font_size (...) |
real32_t | font_height (...) |
real32_t | font_width (...) |
real32_t | font_xscale (...) |
real32_t | font_ascent (...) |
real32_t | font_descent (...) |
real32_t | font_leading (...) |
bool_t | font_is_monospace (...) |
uint32_t | font_style (...) |
void | font_extents (...) |
bool_t | font_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).
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); |
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.
- Use font_create to create a new font.
- Use font_family to get the font typeface.
- Use draw_font to set the font in 2D contexts.
- Use label_font to change the font associated with a Label control.
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.
2. System font
- Use font_system to create a font with the default family.
- Use font_regular_size to get the font size of the interface.
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.
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.
- Use font_monospace to create a generic monospace font.
- Use font_is_monospace to check if a font is monospace.
- Use font_installed_monospace to get all installed monospace fonts.
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
- Use font_style to get the 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).
- ekFBOLD. Bold.
- ekFITALIC. Italic.
- ekFUNDERLINE. Underlined.
- ekFSTRIKEOUT. Strikethrough.
5. Size and metrics
- Use font_size to get the font size.
- Use font_height to get the line size.
- Use font_ascent to obtain the measurement above the baseline.
- Use font_descent to get the measurement below the baseline.
- Use font_leading to get the line margin.
- Use font_extents to get the size of a text.
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.
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.
6. Font stretch
- Use font_with_width to change the average width of the character.
- Use font_with_xscale to change the x scaling of the text.
- Use font_width to get the half width of the character.
- Use font_xscale to get scaling in x.
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.
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.
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.
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.
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 | Operation |
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 | Operation |
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 | Operation |
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 |
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 |
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 |
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 |
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 |
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 |
ArrPt(String) *families = font_installed_families(); ... arrpt_destroy(&families, str_destroy, String); |
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 |
ArrPt(String) *families = font_installed_monospace(); ... arrpt_destroy(&families, str_destroy, String); |
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.