Creating a controller object
The controller object is responsible for building and managing the designspace.
draft
Introduction
In parametric fonts, the designspace is tightly coupled to various measurements (parameters) in the fonts.
During the design stage, the glyph shapes are still changing all the time, and if a measurement changes the parametric designspace must change accordingly.
Why a controller is needed
As designspaces get larger, it becomes harder and harder to keep track and update these relationships by hand.
The controller object takes care of building and managing the designspace, ensuring that file names are consistent and parametric values are always correct and up-do-date.
Duties of the controller
- creating new parametric sources
- setting source names automatically from measurements
- cleaning-up and normalizing UFO sources
- building the parametric designspace from measurements
- copying various kinds of data from the default to other sources
…and much more. See the xProject API documentation for an overview of all methods and attributes available.
The controller object
The xProject controller is a base object which is meant to be subclassed and customized for each project. It provides a basic API for gathering different kinds of data from multiple files, and building a parametric variable font from that.
from xTools4.modules.xproject import xProject
folder = 'MyFolder/'
p = xProject(folder, 'My Family')
p.printSettings()
Default project settings
| base folder | MyFolder/ |
| family name | My Family |
| designspace file | MyFamily.designspace |
| designspace path | MyFolder/Sources/MyFamily.designspace |
| sources folder name | Sources |
| sources folder path | MyFolder/Sources/ |
| default name | wght400 |
| default path | MyFolder/Sources/MyFamily_wght400.ufo |
| measurements file | measurements.json |
| measurements path | MyFolder/Sources/measurements.json |
| smart sets file | MyFamily.roboFontSets |
| smart sets path | MyFolder/Sources/MyFamily.roboFontSets |
| blends file | blends.json |
| blends path | MyFolder/Sources/blends.json |
| tuning folder name | tuning |
| tuning folder path | MyFolder/Sources/tuning/ |
| instances folder name | instances |
| instances folder path | MyFolder/Sources/instances/ |
| fonts folder name | Fonts |
| fonts folder | MyFolder/Fonts/ |
| variable font file | MyFamily.ttf |
| variable font path | MyFolder/Fonts/MyFamily.ttf |
Creating a custom controller
To create a custom controller for your project, start by subclassing xProject. In the example below, we are adding a subfamily argument to the project constructor, and changing the designspace file name and the source folder path to accomodate multiple subfamilies.
from xTools4.modules.xproject import xProject
class MyController(xProject):
def __init__(self, folder, familyName, subFamily):
self.baseFolder = folder
self.familyName = familyName
self.subFamily = subFamily
@property
def designspaceFile(self):
return f"{self.familyName.replace(' ', '')}-{self.subFamily.replace(' ', '')}.designspace"
@property
def sourcesFolder(self):
return os.path.join(self.baseFolder, self.sourcesFolderName, self.subFamily)
p = MyController(folder, 'My Family', 'Roman')
p.printSettings()
This will produce the output below. Notice how the subfamily name Roman is now part of the designspace name and sources folder.
base folder: MyFolder/
family name: My Family
designspace file: MyFamily-Roman.designspace
designspace path: MyFolder/Sources/Roman/MyFamily-Roman.designspace (False)
sources folder name: Sources
sources folder path: MyFolder/Sources/Roman (False)
...
More customization is added during the development of the project as needed.
See the AmstelvarA2 controller and Computer Modern controller for examples of xProject in use.