Font
Usage
For most widget styling, you do not need to create instances of the Font class. Fonts are applied to widgets using style properties:
import toga
from toga.style.pack import pack, SERIF, BOLD
# Create a bold label in the system's serif font at default system size.
my_label = toga.Label("Hello World", font_family=SERIF, font_weight=BOLD)
Toga provides a number of built-in system fonts. Font sizes are specified in CSS points; the default size depends on the platform and the widget.
If you want to use a custom font, the font file must be provided as part of your app's resources, and registered before first use:
import toga
# Register the user font with name "Roboto"
toga.Font.register("Roboto", "resources/Roboto-Regular.ttf")
# Create a label with the new font.
my_label = toga.Label("Hello World", font_family="Roboto")
When registering a font, if an invalid value is provided for the style, variant or weight, NORMAL will be used.
When a font includes multiple weights, styles or variants, each one must be registered separately, even if they're stored in the same file:
import toga
from toga.style.pack import BOLD
# Register a regular and bold font, contained in separate font files
Font.register("Roboto", "resources/Roboto-Regular.ttf")
Font.register("Roboto", "resources/Roboto-Bold.ttf", weight=BOLD)
# Register a single font file that contains both a regular and bold weight
Font.register("Bahnschrift", "resources/Bahnschrift.ttf")
Font.register("Bahnschrift", "resources/Bahnschrift.ttf", weight=BOLD)
A small number of Toga APIs (e.g., Canvas.write_text) do require the use of Font instance. In these cases, you can instantiate a Font using similar properties to the ones used for widget styling:
import toga
from toga.style.pack import BOLD
# Obtain a 14 point Serif bold font instance
my_font = toga.Font(SERIF, 14, weight=BOLD)
# Use the font to write on a canvas.
canvas = toga.Canvas()
canvas.write_text("Hello", font=my_font)
When constructing your own Font instance, ensure that the font family you provide is valid; otherwise an UnknownFontError will be raised.
Notes
- iOS and macOS do not support the use of variant font files (that is, fonts that contain the details of multiple weights/variants in a single file). Variant font files can be registered; however, only the "normal" variant will be used.
- Android and Windows do not support the oblique font style. If an oblique font is specified, Toga will attempt to use an italic style of the same font.
- Android and Windows do not support the small caps font variant. If a Small Caps font is specified, Toga will use the normal variant of the same font.
Reference
Bases: Font
Source code in core/src/toga/fonts.py
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 | class Font(BaseFont):
def __init__(
self,
family: str,
size: int | str,
*,
weight: str = NORMAL,
style: str = NORMAL,
variant: str = NORMAL,
):
"""Construct a reference to a font.
This class should be used when an API requires an explicit font reference (e.g.
[`Canvas.write_text`][toga.Canvas.write_text]). In all other
cases, fonts in Toga are controlled
using the style properties linked below.
:param family: The [font family][toga.style.pack.Pack.font_family].
:param size: The [font size][toga.style.pack.Pack.font_size].
:param weight: The [font weight][toga.style.pack.Pack.font_weight].
:param style: The [font style][toga.style.pack.Pack.font_style].
:param variant: The [font variant][toga.style.pack.Pack.font_variant].
:raises UnknownFontError: If the font family requested corresponds to neither
one of the [built-in system fonts][toga.style.pack.Pack.font_family], nor a
user-registered font, nor (depending on platform) a font installed on the
system.
:raises ValueError: If a user-registered font is used, but the file specified
either doesn't exist or a font can't be successfully loaded from it.
"""
super().__init__(family, size, weight=weight, style=style, variant=variant)
self.factory = get_factory()
try:
self._impl = _IMPL_CACHE[self]
except KeyError:
self._impl = self.factory.Font(self)
try:
self._impl.load_predefined_system_font()
except UnknownFontError:
try:
self._impl.load_user_registered_font()
except UnknownFontError:
try:
self._impl.load_arbitrary_system_font()
except UnknownFontError as exc:
raise UnknownFontError(f"Unknown font '{self}'") from exc
def __str__(self) -> str:
size = (
"default size"
if self.size == SYSTEM_DEFAULT_FONT_SIZE
else f"{self.size}pt"
)
string = f"{self.family} {size} {self.weight} {self.variant} {self.style}"
return string.replace(" normal", "")
@staticmethod
def register(
family: str,
path: str | Path,
*,
weight: str = NORMAL,
style: str = NORMAL,
variant: str = NORMAL,
) -> None:
"""Register a file-based font.
:param family: The [font family][toga.style.pack.Pack.font_family].
:param path: The path to the font file. This can be an absolute path, or a path
relative to the module that defines your [`App`][toga.App] class.
:param weight: The [font weight][toga.style.pack.Pack.font_weight].
:param style: The [font style][toga.style.pack.Pack.font_style].
:param variant: The [font variant][toga.style.pack.Pack.font_variant].
relative to the module that defines your :any:`App` class.
:raises ValueError: When the registered family has the same name as the standard
font families ``"cursive"``, ``"fantasy"``, ``"message"``, ``"monospace"``,
`"sans-serif"``, "serif", or "system".
"""
if family in (
CURSIVE,
FANTASY,
MESSAGE,
MONOSPACE,
SANS_SERIF,
SERIF,
SYSTEM,
):
raise ValueError(
"Custom fonts cannot be registered with a built-in font family name"
)
font_key = Font._registered_font_key(family, weight, style, variant)
_REGISTERED_FONT_CACHE[font_key] = str(toga.App.app.paths.app / path)
@staticmethod
def _registered_font_key(
family: str,
weight: str,
style: str,
variant: str,
) -> tuple[str, str, str, str]:
if weight not in constants.FONT_WEIGHTS:
weight = NORMAL
if style not in constants.FONT_STYLES:
style = NORMAL
if variant not in constants.FONT_VARIANTS:
variant = NORMAL
return family, weight, style, variant
|
__init__(family, size, *, weight=NORMAL, style=NORMAL, variant=NORMAL)
Construct a reference to a font.
This class should be used when an API requires an explicit font reference (e.g.
Canvas.write_text). In all other
cases, fonts in Toga are controlled
using the style properties linked below.
:param family: The font family.
:param size: The font size.
:param weight: The font weight.
:param style: The font style.
:param variant: The font variant.
:raises UnknownFontError: If the font family requested corresponds to neither
one of the built-in system fonts, nor a
user-registered font, nor (depending on platform) a font installed on the
system.
:raises ValueError: If a user-registered font is used, but the file specified
either doesn't exist or a font can't be successfully loaded from it.
Source code in core/src/toga/fonts.py
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 | def __init__(
self,
family: str,
size: int | str,
*,
weight: str = NORMAL,
style: str = NORMAL,
variant: str = NORMAL,
):
"""Construct a reference to a font.
This class should be used when an API requires an explicit font reference (e.g.
[`Canvas.write_text`][toga.Canvas.write_text]). In all other
cases, fonts in Toga are controlled
using the style properties linked below.
:param family: The [font family][toga.style.pack.Pack.font_family].
:param size: The [font size][toga.style.pack.Pack.font_size].
:param weight: The [font weight][toga.style.pack.Pack.font_weight].
:param style: The [font style][toga.style.pack.Pack.font_style].
:param variant: The [font variant][toga.style.pack.Pack.font_variant].
:raises UnknownFontError: If the font family requested corresponds to neither
one of the [built-in system fonts][toga.style.pack.Pack.font_family], nor a
user-registered font, nor (depending on platform) a font installed on the
system.
:raises ValueError: If a user-registered font is used, but the file specified
either doesn't exist or a font can't be successfully loaded from it.
"""
super().__init__(family, size, weight=weight, style=style, variant=variant)
self.factory = get_factory()
try:
self._impl = _IMPL_CACHE[self]
except KeyError:
self._impl = self.factory.Font(self)
try:
self._impl.load_predefined_system_font()
except UnknownFontError:
try:
self._impl.load_user_registered_font()
except UnknownFontError:
try:
self._impl.load_arbitrary_system_font()
except UnknownFontError as exc:
raise UnknownFontError(f"Unknown font '{self}'") from exc
|
register(family, path, *, weight=NORMAL, style=NORMAL, variant=NORMAL)
staticmethod
Register a file-based font.
:param family: The font family.
:param path: The path to the font file. This can be an absolute path, or a path
relative to the module that defines your App class.
:param weight: The font weight.
:param style: The font style.
:param variant: The font variant.
relative to the module that defines your :any:App class.
:raises ValueError: When the registered family has the same name as the standard
font families "cursive", "fantasy", "message", "monospace",
`"sans-serif"``, "serif", or "system".
Source code in core/src/toga/fonts.py
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135 | @staticmethod
def register(
family: str,
path: str | Path,
*,
weight: str = NORMAL,
style: str = NORMAL,
variant: str = NORMAL,
) -> None:
"""Register a file-based font.
:param family: The [font family][toga.style.pack.Pack.font_family].
:param path: The path to the font file. This can be an absolute path, or a path
relative to the module that defines your [`App`][toga.App] class.
:param weight: The [font weight][toga.style.pack.Pack.font_weight].
:param style: The [font style][toga.style.pack.Pack.font_style].
:param variant: The [font variant][toga.style.pack.Pack.font_variant].
relative to the module that defines your :any:`App` class.
:raises ValueError: When the registered family has the same name as the standard
font families ``"cursive"``, ``"fantasy"``, ``"message"``, ``"monospace"``,
`"sans-serif"``, "serif", or "system".
"""
if family in (
CURSIVE,
FANTASY,
MESSAGE,
MONOSPACE,
SANS_SERIF,
SERIF,
SYSTEM,
):
raise ValueError(
"Custom fonts cannot be registered with a built-in font family name"
)
font_key = Font._registered_font_key(family, weight, style, variant)
_REGISTERED_FONT_CACHE[font_key] = str(toga.App.app.paths.app / path)
|
Bases: Exception
Raised when an unknown font family is requested.
Source code in core/src/toga/fonts.py
| class UnknownFontError(Exception):
"""Raised when an unknown font family is requested."""
|