@startuml v5_class_diagram title Designspace v5 Class Diagram Note: the ""Descriptor"" suffix is omitted from most classes end title ' left to right direction skinparam class { BackgroundColor<> PaleGreen } class DesignSpaceDocument { + formatVersion: str = None + <> elidedFallbackName: str = None + rulesProcessingLast: bool = False + lib: Dict = {} } note left of DesignSpaceDocument::elidedFallbackName STAT Style Attributes Header field ""elidedFallbackNameID"" end note abstract class AbstractAxis { + tag: str + name: str + labelNames: Dict[str, str] + hidden: bool + map: List[Tuple[float, float]] + <> axisOrdering: int } DesignSpaceDocument *-- "*" AbstractAxis: axes > note right of AbstractAxis::axisOrdering STAT Axis Record field end note class Axis { + minimum: float + maximum: float + default: float } AbstractAxis <|--- Axis note bottom of Axis This is the usual Axis, with a range of values. end note class DiscreteAxis <> { + values: List[float] + default: float } AbstractAxis <|--- DiscreteAxis note bottom of DiscreteAxis A discrete axis is not interpolable, e.g. Uprights vs Italics, and so has "discrete" stops instead of a continuous range of values. end note Axis .[hidden] DiscreteAxis class AxisLabel <> { + userMinimum: Optional[float] + userValue: float + userMaximum: Optional[float] + name: str + elidable: bool + olderSibling: bool + linkedUserValue: Optional[float] + labelNames: Dict[str, str] + getFormat(): 1 | 2 | 3 } note right of AxisLabel Label for a stop on an Axis (STAT format 1,2,3) end note AbstractAxis *-- "*" AxisLabel: <> \n axisLabels > class LocationLabel <> { + name: str + location: Dict[str, float] + elidable: bool + olderSibling: bool + labelNames: Dict[str, str] } note right of LocationLabel Label for a freestanding location (STAT format 4) end note DesignSpaceDocument *--- "*" LocationLabel: <> \n locationLabels > class Rule { + name: str + conditionSets: List[ConditionSet] + subs: Dict[str, str] } DesignSpaceDocument *- "*" Rule: rules > class Source { + name: Optional[str] + filename: str + path: str + layerName: Optional[str] + <> location: Location + <> designLocation: SimpleLocation .... + font: Optional[Font] .... + familyName: Optional[str] + styleName: Optional[str] + <> localisedFamilyName: Dict .... + <> copyLib: bool + <> copyInfo: bool + <> copyGroups: bool + <> copyFeatures: bool .... + muteKerning: bool + muteInfo: bool + mutedGlyphNames: List[str] ---- + <> getFullDesignLocation(doc) } DesignSpaceDocument *-- "*" Source: sources > note right of Source::localisedFamilyName New field to allow generation of localised instance names using STAT information. end note note right of Source::copyGroups These fields are already not meaningful anymore in version 4 (the default source will be used as "neutral" for groups, info and features. ''copyLib'' can be emulated by putting content in the designspace's lib. end note note as NLocSource The location of sources can still only be defined in design coordinates, and now also by relying on axis defaults. To build the final, "full" location, a helper method is provided, that uses axis defaults and axis mappings to fill in the blanks. end note NLocSource . Source::designLocation NLocSource . Source::getFullDesignLocation class VariableFont <> { + filename: str + lib: Dict } DesignSpaceDocument *--- "*" VariableFont: <> \n variableFonts > note right of VariableFont A variable font is a subset of the designspace where everything interpolates (and so can be compiled into an OpenType variable font). end note abstract class AbstractAxisSubset <> { + name: str } VariableFont *-- "*" AbstractAxisSubset: <> \n axisSubsets > note right of AbstractAxisSubset An axis subset selects a range or a spot on each the available axes from the whole designspace. By default, only the default value of each axis is used to define the variable font. Continuous axes can be specified to include their full range instead; or a subset of the range. Discrete axes can be specified to include a different spot than the default. end note class RangeAxisSubset <> { + userMinimum: float + userDefault: float + userMaximum: float } AbstractAxisSubset <|-- RangeAxisSubset class ValueAxisSubset <> { + userValue: float } AbstractAxisSubset <|-- ValueAxisSubset class Instance { + filename: str + path: str + <> location: Location + <> locationLabel: str + <> designLocation: AnisotropicLocation + <> userLocation: SimpleLocation .... + font: Optional[Font] .... + <> name: Optional[str] + <> familyName: Optional[str] + <> styleName: Optional[str] + <> postScriptFontName: Optional[str] + <> styleMapFamilyName: Optional[str] + <> styleMapStyleName: Optional[str] + localisedFamilyName: Dict + localisedStyleName: Dict + localisedStyleMapFamilyName: Dict + localisedStyleMapStyleName: Dict .... + <> glyphs: Dict + <> kerning: bool + <> info: bool .... + lib: Dict ---- + <> clearLocation() + <> getLocationLabelDescriptor(doc) + <> getFullDesignLocation(doc) + <> getFullUserLocation(doc) } DesignSpaceDocument *-- "*" Instance: instances > note right of Instance::locationLabel The location can now alternatively be a string = name of a LocationLabel (STAT format 4). The instance then adopts the location of that label. See the Decovar example file. end note note right of Instance::styleMapStyleName All the name field are now optional. Their default values will be computed using the provided STAT table data and the STAT rules from the spec. For styleMap{Family,Style}Name, they would be computed using the STAT ""linkedUserValue"" fields. end note note right of Instance::glyphs This attribute has been replaced by rules end note note right of Instance::kerning All instances get kerning and info nowadays. end note note as NLocInstance The location of instances can now be defined using either: - a STAT LocationLabel - design coordinates - user coordinates. - relying on axis defaults To build the final, "full" location, a few helper methods are provided, that aggregate data from these sources and apply the axis mappings. end note NLocInstance . Instance::designLocation NLocInstance . Instance::getFullDesignLocation @enduml