enthought / enthought/pyface

Pyface Fonts

Open
#600 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
115
Forks
54
PR merge metrics
No merged PRs in 30d

Description

Currently there is no cross-toolkit way to specify a font selection in Pyface. This is a problem.

There is a Font trait in TraitsUI that produces a (subclass of a) toolkit font value as a mapped value, but this requires a toolkit to be imported and operational at class definition time (so usually at module import time), so there is no way to defer toolkit imports until class instantiation, which is often a cause of problems. The TraitsUI Font traits can be found in https://github.com/enthought/traitsui/blob/master/traitsui/qt4/font_trait.py and https://github.com/enthought/traitsui/blob/master/traitsui/wx/font_trait.py. The core features they have are:

- they accept and hold toolkit font values (subclasses of `QFont` or `wx.Font` respectively)
- they have an ad-hoc ability to accept strings which describe fonts (eg. `Font("12pt roman bold")` (the parser, such as it is, is [here](https://github.com/enthought/traitsui/blob/6416e49cd707eca9a71736ea6ee9704d496deded/traitsui/wx/font_trait.py#L71) and [here](https://github.com/enthought/traitsui/blob/6416e49cd707eca9a71736ea6ee9704d496deded/traitsui/qt4/font_trait.py#L71))

There is an additional [KivaFontTrait in Kiva](https://github.com/enthought/enable/blob/master/kiva/trait_defs/kiva_font_trait.py) which accepts similar string values, but holds a [Kiva Font object](https://github.com/enthought/enable/blob/master/kiva/fonttools/font.py) which is nominally toolkit independent, but which has several severe bugs in its implementation (see https://github.com/enthought/enable/issues/404 for example) and which [has a derived version in Enable](https://github.com/enthought/enable/blob/6cf525cbeefdf34dc6eac5e54d7a73f755ea79b1/enable/enable_traits.py#L94). This font trait subclasses the TraitsUI FontEditor (but only on wx) to [produce an editor](https://github.com/enthought/enable/blob/master/kiva/trait_defs/ui/wx/kiva_font_editor.py) which requires converting to and from the Kiva font and wx.Font. A number of the issues with the Kiva fonts stem from the fact that they don't match precisely to the OpenType/TrueType font systems which allow additional font styles, such as more nuanced font weights, additional font variants, expanded and condensed fonts, and so on.

Inspection of these shows lots of common (or _almost_ common code) (eg. at least 3 versions of essentially the same parser).

There is no reason why these should be separate objects.

The most common uses of these classes are in Enable and Chaco, where they are typically used with string values, rather than toolkit values, because the string values work cross-toolkit (ie. if you say `Font(QFont(...))` in a class, then you have a problem on Wx).

Additional concerns that need to be considered when dealing with fonts are that the specific font you want may not be available, and so these traits and classes have ways of specifying alternative choices when a preferred font is not available.

There should be, in Pyface, a class which:
- is toolkit independent
- can be imported by code without side-effects
- is at least as expressive as the current font traits, and ideally is _more_ expressive (eg. it would be a nice-to-have to be able to support font weights beyond "bold", or other font options)
- can be converted to and from toolkit font classes with minimal loss of fidelity
- is appropriate for use in Kiva, Enable, and Chaco as well

There should also be a corresponding trait type which:
- holds values of the class
- has affordances for users who are writing and using classes that use the trait; in particular it is desirable to be able to use a string description of a font, particularly if the description is well-understood.

The font description should therefore:
- have a well-defined format
- have a parser which has had some design thought put into it
- have solid tests
- be able to be converted to and from a font class with no loss of fidelity

One possibility for the description language is a (subset of) CSS font descriptors (eg. https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#propdef-font) which would give an additional benefit of making it easy to express the font for use in HTML (eg. as the default font of an HTML editor). CSS isn't a perfect fit, because it is _cascading_, so it has ways of expressing relative propeties (bigger/smaller, lighter/heavier, etc.) which don't make as much sense here.

Another alternative is to avoid string descriptions, but
```
from pyface.font import PyfaceFont
from chaco.api import Label

my_label = Label(font=PyfaceFont(size=24.0, weight="bold", family=["Comic Sans"])
```
is not as nice as
```
from chaco.api import Label

my_label = Label(font='bold 24.0px "Comic Sans"')
```
when what you want to concentrate on is writing Chaco code, particularly for scientist-coders.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.