Source code for pyface.util.font_parser
# (C) Copyright 2005-2023 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!
GENERIC_FAMILIES = {
'default', 'fantasy', 'decorative', 'serif', 'roman', 'cursive', 'script',
'sans-serif', 'swiss', 'monospace', 'modern', 'typewriter', 'teletype'
}
WEIGHTS = {
'thin', 'extra-light', 'light', 'regular', 'medium', 'demi-bold',
'bold', 'extra-bold', 'heavy', 'extra-heavy'
}
STRETCHES = {
'ultra-condensed', 'extra-condensed', 'condensed',
'semi-condensed', 'semi-expanded', 'expanded', 'extra-expanded',
'ultra-expanded'
}
STYLES = {'italic', 'oblique'}
VARIANTS = {'small-caps'}
DECORATIONS = {'underline', 'strikethrough', 'overline'}
NOISE = {'pt', 'point', 'px', 'family'}
[docs]class FontParseError(ValueError):
"""An exception raised when font parsing fails."""
pass
[docs]def simple_parser(description):
"""An extremely simple font description parser.
The parser is simple, and works by splitting the description on whitespace
and examining each resulting token for understood terms:
Size
The first numeric term is treated as the font size.
Weight
The following weight terms are accepted: 'thin', 'extra-light',
'light', 'regular', 'medium', 'demi-bold', 'bold', 'extra-bold',
'heavy', 'extra-heavy'.
Stretch
The following stretch terms are accepted: 'ultra-condensed',
'extra-condensed', 'condensed', 'semi-condensed', 'semi-expanded',
'expanded', 'extra-expanded', 'ultra-expanded'.
Style
The following style terms are accepted: 'italic', 'oblique'.
Variant
The following variant terms are accepted: 'small-caps'.
Decorations
The following decoration terms are accepted: 'underline',
'strikethrough', 'overline'.
Generic Families
The following generic family terms are accepted: 'default', 'fantasy',
'decorative', 'serif', 'roman', 'cursive', 'script', 'sans-serif',
'swiss', 'monospace', 'modern', 'typewriter', 'teletype'.
In addtion, the parser ignores the terms 'pt', 'point', 'px', and 'family'.
Any remaining terms are combined into the typeface name. There is no
expected order to the terms.
This parser is roughly compatible with the various ad-hoc parsers in
TraitsUI and Kiva, allowing for the slight differences between them and
adding support for additional options supported by Pyface fonts, such as
stretch and variants.
Parameters
----------
description : str
The font description to be parsed.
Returns
-------
properties : dict
Font properties suitable for use in creating a Pyface Font.
Notes
-----
This is not a particularly good parser, as it will fail to properly
parse something like "10 pt times new roman" or "14 pt computer modern"
since they have generic font names as part of the font face name.
"""
face = []
generic_family = ""
size = None
weight = "normal"
stretch = "normal"
style = "normal"
variants = set()
decorations = set()
for word in description.lower().split():
if word in NOISE:
continue
elif word in GENERIC_FAMILIES:
generic_family = word
elif word in WEIGHTS:
weight = word
elif word in STRETCHES:
stretch = word
elif word in STYLES:
style = word
elif word in VARIANTS:
variants.add(word)
elif word in DECORATIONS:
decorations.add(word)
else:
if size is None:
try:
size = float(word)
continue
except ValueError:
pass
face.append(word)
family = []
if face:
family.append(" ".join(face))
if generic_family:
family.append(generic_family)
if not family:
family = ["default"]
if size is None:
size = 12
return {
'family': family,
'size': size,
'weight': weight,
'stretch': stretch,
'style': style,
'variants': variants,
'decorations': decorations,
}