Python API

Auto-generated from JavaScript object model introspection

Table of Contentslink


Overviewlink

The Font Object Model provides an object-oriented interface for manipulating font data. All objects are lightweight facades over the underlying JSON data - changes are immediately reflected in the font structure.

Accessing the Font Modellink

# Get the current font (fonteditor module is pre-loaded)
font = Font()

Dictionary Access (Python wrappers)link

Dictionary-like object model fields are wrapped as live Python mappings. Use normal Python dictionary access for both reading and writing.

font = Font()
master = font.masters[0]

# Nested kerning dictionary (live two-way view)
master.kerning["A"]["V"] = -80

# Internationalized naming dictionaries
font.names.familyName["dflt"] = "My Family"
font.names.familyName["de"] = "Meine Familie"
font.names.familyName["fr"] = "Ma Famille"
font.names.familyName["ar"] = "عائلتي"
master.name["dflt"] = "Standard"
master.name["de"] = "Standard"
master.name["fr"] = "Standard"
master.name["ar"] = "قياسي"

# Optional snapshot copy when needed
kerning_snapshot = master.kerning.as_dict()

Shared Plugin Contextlink

ctx = Context()
ctx.runCount = getattr(ctx, "runCount", 0) + 1
SetContextPatch({"lastRun": {"count": ctx.runCount}})

Parent Navigationlink

All objects in the hierarchy have a parent() method that returns their parent object, allowing navigation up the object tree to the root Font object.

Example:

# Navigate from node up to font
node = font.glyphs[0].layers[0].paths[0].nodes[0]
path = node.parent()      # Path object
shape = path.parent()     # Shape object
layer = shape.parent()    # Layer object
glyph = layer.parent()    # Glyph object
font = glyph.parent()     # Font object

Class Referencelink

Fontlink

Access:

# fonteditor module is pre-loaded
font = Font()

Propertieslink

Read/Write Properties

  • upm (float | int)
  • version ([number, number])
  • axes (list[Axis] | None)
  • instances (list[Instance] | None)
  • masters (list[Master] | None)
  • note (str | None)
  • date (str)
  • names (dict[str, dict[str, str] | None])
  • custom_ot_values (list[Unsafe] | None)
  • variation_sequences (dict | None)
  • features (dict[str, Any])
  • first_kern_groups (dict | None)
  • second_kern_groups (dict | None)
  • format_specific (dict | None)
  • source (str | None)

Read-Only Properties

Methodslink

rebuildAutomaticCompositesForGlyphs(changedGlyphNames: Set<string> | None = None, options: { allowedGlyphNames?: Set<string>; preferredLayerId?: string | null; preferredSourceGlyphName?: string | null; } | None = None) -> Set<string>

collectMetricsKeyDependentGlyphs(sourceGlyphNames: Iterable<string>) -> Set<string>

Collect glyphs whose metrics keys / automatic-offset edges depend on the given source glyphs, whether or not their stored sidebearings currently need updating. Used by cascading commit so live-already-synced dependents are still persisted into Yjs.

collectMetricsKeyPrerequisiteGlyphs(glyphNames: Iterable<string>) -> Set<string>

Return the transitive metrics-key prerequisites of glyphs that must be recomposed live. A visible glyph can reference a hidden glyph through a metrics key (for example a.ss03 =|n); its value is not correct until the hidden reference and its own prerequisites have settled. The live recomposition closure uses this to close its allowed mutation set before running the same work queue as the all-scope commit path.

recomputeMetricsKeys(changedGlyphNames: Set<string> | None = None, options: { allowedGlyphNames?: Set<string>; skipAutomaticCompositeRebuild?: boolean; /** The caller already rebuilt automatic composites for the initial * sources | None = None, but metric-induced changes must still rebuild their * own automatic dependents. */ skipInitialAutomaticCompositeRebuild?: boolean; }) -> Set<string>

findGlyph(name: str) -> [Glyph](#glyph) | None

Find a glyph by name

Example:

glyph = font.findGlyph("A")
if glyph:
    print(glyph.name)

renameGlyphs(renameMap: ReadonlyMap<string, string>) -> None

Rename glyphs and every font-owned reference to them in one undoable transaction. The mapping is simultaneous, so swaps are safe.

resolveGlyphView(name: str) -> [Glyph](#glyph) | FeatureVariationGlyph | None

Resolve an editor glyph token to an authorable layer view. A literal glyph name resolves to its persisted Glyph; base.feaVar.N resolves to the corresponding synthetic feature-variation family.

findGlyphByCodepoint(codepoint: float | int) -> [Glyph](#glyph) | None

Find a glyph by codepoint

Example:

glyph = font.findGlyphByCodepoint(0x0041)  # Find 'A'

invalidateReverseComponentIndex() -> None

invalidateMetricsKeyDependencyEntries() -> None

Drop only the metrics-key dependency cache. Call when a metrics key is added, changed, or removed without the glyph set changing.

getGlyphNamesByLengthDesc() -> list[str]

Returns glyph names sorted by length descending, cached. Used by metrics-key parsing for longest-prefix matching. Cache is invalidated when glyphs are added/removed/renamed (see invalidateReverseComponentIndex).

findDirectGlyphsUsingComponent(componentGlyphName: str) -> list[str]

collectComponentDependentGlyphs(componentGlyphNames: Iterable<string>, options: { includeSourceGlyphNames?: boolean; retainGlyphNames?: Set<string>; } | None = None) -> Set<string>

invalidateLayoutCachesForGlyphs(glyphNames: Iterable<string>) -> None

Invalidate automatic composition layout caches for all layers of the specified glyphs. Call before recomputing compositions so that stale cached layouts from a previous frame are not reused.

findGlyphsUsingComponent(componentGlyphName: str) -> list[str]

Find all glyphs that reference a given glyph as a component This recursively finds glyphs at each nesting level

Example:

glyphs = font.findGlyphsUsingComponent("o")
# Returns ["ö", "õ", "ø", ...] if they use "o" as a component

duplicateGlyph(glyph: [Glyph](#glyph), newName: str) -> [Glyph](#glyph)

Duplicate a glyph with a new name, inserted immediately after the source. The duplicate does not keep Unicode codepoints.

Example:

new_glyph = font.duplicateGlyph(glyph, "A.alt")

allocateUniqueGlyphName(baseName: str) -> str

Next free glyph name using Glyphs-style .001 / .002 suffixes. aa; if taken → a.001, then a.002, …

duplicateGlyphs(names: Iterable<string>) -> list[[Glyph](#glyph)]

Duplicate each named glyph under a unique .001-style name. Each clone is inserted directly after its source, loses codepoints, regenerates layer IDs, and keeps master references.

findAxis(id: str) -> [Axis](#axis) | None

Find an axis by ID

findAxisByTag(tag: str) -> [Axis](#axis) | None

Find an axis by tag

Example:

weight_axis = font.findAxisByTag("wght")

findMaster(id: str) -> [Master](#master) | None

Find a master by ID

addMaster(master: Babelfont.Master | None = None, options: AddMasterOptions | None = None) -> Promise<Master | null>

removeMastersByIds(masterIds: list[str]) -> Promise<boolean>

findInsertIndexAfterName(baseName: str) -> float | int

Index at which to insert a new glyph that belongs with baseName. Strips a trailing .NNN so clipboard names like a.001 still land with the a / a.NNN family. Prefers immediately after the last existing family sibling; otherwise appends.

addGlyph(name: str, category: Babelfont.GlyphCategory | str, options: { insertIndex?: number } | None = None) -> [Glyph](#glyph)

Add a new glyph to the font

Example:

glyph = font.addGlyph("myGlyph", "Base")

addGlyphs(glyphs: Array<{ name: string; codepoints: number[]; category?: Babelfont.GlyphCategory | string; }>) -> list[[Glyph](#glyph)]

Add several Unicode-backed glyphs as one undoable document edit.

preflightDeleteGlyphs(names: Iterable<string>) -> GlyphDeletePreflight

Count cleanup hits for a proposed glyph deletion and collect preview details for the confirm dialog.

deleteGlyphs(names: Iterable<string>) -> None

Delete glyphs and clean font-owned references in one undoable transaction. Always cleans features/classes/prefixes, metrics keys, components, kerning (LTR + RTL), and kern-group membership (dropping empty groups).

removeGlyph(name: str) -> bool

Remove a glyph by name

Example:

font.removeGlyph("oldGlyph")

toJSONString(options: { compileFacing?: boolean } | None = None) -> str

Serialize the font back to JSON string

fromJSONString(json: str) -> [Font](#font)

Create a Font instance from JSON string

fromData(data: Babelfont.Font) -> [Font](#font)

Create a Font instance from parsed JSON data

toString() -> str

analyzeFeatureTables(featureTag: str) -> { hasGSUB: boolean; hasGPOS: boolean; }

Analyze a feature's code to determine if it contains GSUB and/or GPOS rules

Example:

const analysis = font.analyzeFeatureTables("liga")
if (analysis.hasGSUB) console.log("Feature has substitution rules")

analyzeOpenTypeCode(code: str) -> { hasGSUB: boolean; hasGPOS: boolean; }

Analyze OpenType feature code to determine if it contains GSUB and/or GPOS rules This is a general-purpose method that can analyze code from features, prefixes, or other sources

Example:

const analysis = font.analyzeOpenTypeCode("substitute a by b;")
if (analysis.hasGSUB) console.log("Code contains substitution rules")

analyzePrefix(prefixName: str) -> { hasGSUB: boolean; hasGPOS: boolean; }

Analyze a prefix's code to determine if it contains GSUB and/or GPOS rules

Example:

const analysis = font.analyzePrefix("myLookup")
if (analysis.hasGSUB) console.log("Prefix contains substitution rules")

Glyphlink

Access:

glyph = font.glyphs[0]
# or
glyph = font.findGlyph("A")

Propertieslink

Read/Write Properties

  • leftMetricsKey (str | None)
  • rightMetricsKey (str | None)
  • name (str)
  • production_name (str | None)
  • category (Babelfont.GlyphCategory)
  • codepoints (list[float | int] | None)
  • exported (bool | None)
  • direction (Babelfont.Direction | None)
  • format_specific (dict | None)

Read-Only Properties

  • featureVariations (list[FeatureVariationGlyph]): Synthetic, authorable views over this glyph's raw Glyphs feature-variation layers.
  • BUILTIN_CATEGORIES (Any)
  • glyphData (GlyphDataSearchResult | None): Read-only Unicode metadata from the bundled Glyph Data catalog. Encoded base glyphs win over editable glyph names; dotted glyphs inherit the identity of their base glyph before a name fallback is attempted.
  • layers (list[Layer] | None)
  • isCompatible (bool): Returns True/False based on whether the outline structure (components + paths + anchors) is compatible across all main layers of this glyph.

Methodslink

getPathSegment() -> list[(string | number)]

getFeatureVariationLayerEntries(familyId: str | None = None) -> Array<{ familyId: string; layer: Layer }>

addFeatureVariation(axisRules: list[Unsafe]) -> FeatureVariationGlyph

Create one associated feature-variation layer for every base master layer, copying each layer's materialized background when present.

removeFeatureVariation(featureVariation: FeatureVariationGlyph | str) -> None

Delete every raw layer belonging to a feature-variation family.

normalizeCategory(value: Babelfont.GlyphCategory | str | None) -> Babelfont.GlyphCategory

addLayer(width: float | int, master: Babelfont.LayerType | None = None, requestedLayerId: str | None | None = None) -> [Layer](#layer)

Add a new layer to the glyph

Example:

layer = glyph.addLayer(500)  # 500 units wide

addBackgroundLayer(foreground: [Layer](#layer)) -> [Layer](#layer)

removeLayer(index: float | int) -> None

Remove a layer at the specified index

removeLayerById(id: str) -> None

Remove a layer by its backing-array ID.

findLayerById(id: str) -> [Layer](#layer) | None

Find a layer by ID

findLayerByMasterId(masterId: str) -> [Layer](#layer) | None

Find a layer by master ID

calculateOutlineCompatibility() -> { compatible: boolean; layerCount: number; referenceLayerId?: string; incompatibleLayerIds: string[]; }

Compare outline structure across main layers (the same list shown in the UI).

For compatibility checks, mixed shape sequences are normalized by moving components before paths while preserving their relative order inside each type.

toString() -> str


FeatureVariationGlyphlink

An authorable view over one conditional Glyphs feature-variation layer family.

Propertieslink

All properties are read-only:

  • name (str)
  • axisRules (list[Unsafe])
  • layers (list[Layer])

Methodslink

setAxisRules(axisRules: list[Unsafe]) -> FeatureVariationGlyph

Replace the shared Glyphs feature-variation rules on every raw family layer.

findLayerById(id: str) -> [Layer](#layer) | None

findLayerByMasterId(masterId: str) -> [Layer](#layer) | None

addLayer(width: float | int, master: Babelfont.LayerType | None = None, requestedLayerId: str | None | None = None) -> [Layer](#layer)

removeLayer(index: float | int) -> None

removeLayerById(id: str) -> None

toString() -> str


Layerlink

Layer in a glyph representing a master or intermediate design

Access:

layer = glyph.layers[0]

Propertieslink

Read/Write Properties

  • leftMetricsKey (str | None)
  • rightMetricsKey (str | None)
  • width (float | int)
  • lsb (float | int): Get the left sidebearing (LSB) - the distance from x=0 to the left edge of the bounding box
  • rsb (float | int): Get the right sidebearing (RSB) - the distance from the right edge of the bounding box to the advance width
  • linked (bool): Whether this layer is linked for editor multi-layer operations. This is editor-only runtime state keyed by glyph and layer ID; it is not persisted into font data.
  • name (str | None)
  • id (str | None)
  • master (Babelfont.LayerType | None)
  • smart_component_location (UserspaceLocation | None)
  • selection (list[SelectableLayerObject]): Current UI selection on this layer. Assign a node, anchor, component, guide, or a list of them to replace the selection.
  • color (Babelfont.Color | None)
  • layer_index (float | int | None)
  • is_background (bool | None)
  • background_layer_id (str | None)
  • location (DesignspaceLocation | None)
  • format_specific (dict | None)

Read-Only Properties

  • guides (list[Guide] | None)
  • paths (list[Path]): Direct path objects in this layer, ready to use without Shape.asPath()
  • components (list[Component]): Direct component objects in this layer, ready to use without Shape.asComponent()
  • anchors (list[Anchor] | None)
  • backgroundLayer (Layer): The paired background layer. Empty backgrounds are transient until a path is added, so merely accessing this property does not alter the glyph.
  • fingerprint (str): Returns a normalized outline-compatibility fingerprint for this layer. The fingerprint includes components, paths, and anchors, with anchors sorted by name and guides excluded.

Methodslink

toJSON() -> Unsafe

[object Object],[object Object],[object Object]

toCompileJSON() -> Unsafe

Compile-facing serialization: applies automatic =+/-= left offsets to component translates so fontc / worker preview see physical ink and advance. Must not be written back into the resting model or Yjs.

invalidateShapeCache() -> None

Force shape wrapper rebuild on next access. Call after replacing data.shapes externally so that setDirectSidebearing operates on the current shapes array.

invalidateContentCaches() -> None

invalidateLayoutCache() -> None

Invalidate only the automatic composition layout cache. Cheaper than full invalidateContentCaches() when only anchor/composition state has changed (not shapes/guides).

getAutomaticCompositionSourceCacheKey() -> object

syncFromEditorLayerData(layerData: { width: number; height?: number; vertWidth?: number; shapes?: Unsafe[]; anchors?: Unsafe[]; guides?: Unsafe[]; format_specific?: Record<string, Unsafe>; }) -> None

Bulk-sync mutable properties from the outline editor's working copy into this layer's model data. Skips the expensive toJSON() round-trip and layout recomputation that would otherwise occur for automatic-aligned layers.

Must be called inside withSuppressedModelRecording so that the individual property mutations don't trigger recordAndMarkDirty.

clearEffectiveSidebearingKey(side: SidebearingSide) -> None

setDirectSidebearing(side: SidebearingSide, value: float | int) -> None

translateMaterializedBackgroundLayerContentsX(deltaX: float | int) -> None

Keep an existing background drawing aligned with a foreground X shift. Virtual empty backgrounds remain unmaterialized and are intentionally ignored.

recomputeOwnMetricsKeys() -> bool

Resolve and apply this layer's own metrics keys (left/right) without scanning the full font. Use during interactive editing (keyboard/mouse) where only the current layer needs updating.

isAutomaticAlignedLayer() -> bool

assignAutomaticCompositeKerningGroups() -> bool

Copy kerning groups from resolved automatic bases onto this glyph. Invoked only when enabling automatic alignment makes the layer automatic.

getAutomaticComponentTargetAnchorOptions(component: [Component](#component)) -> list[str]

rebuildAutomaticComposition(sourceDataCache: WeakMap<object | None = None, AutomaticCompositionSourceData>) -> bool

applyAutomaticCompositionToLayerData(layerData: { shapes?: Unsafe[]; width?: number; }, sourceDataCache: WeakMap<object | None = None, AutomaticCompositionSourceData>) -> bool

Apply automatic component anchoring and derived width to mutable layer data without mutating the model layer itself.

This is used by live editor interactions, such as resize-box scaling, where component transforms are already edited on a working copy and only the automatic translations and width need to be refreshed.

resolveMetricsKey(side: SidebearingSide, stack: Set<string>) -> MetricsKeyResolution

applySidebearingInput(side: SidebearingSide, rawValue: str) -> MetricsKeyResolution

getPathSegment() -> list[(string | number)]

getMaster() -> [Master](#master) | None

Get the resolved master object for this layer. Returns a Master only when this layer is a DefaultForMaster layer.

getComputedName() -> str

findAnchor(anchorName: str) -> [Anchor](#anchor) | None

addShape(shape: Babelfont.Shape) -> [Shape](#shape)

Add a new shape to the layer

addPath(closed: bool | dict, Unsafe>) -> [Path](#path)

Add a new path to the layer

Example:

path = layer.addPath(closed=True)

addComponent(reference: str, transform: list[float | int] | Babelfont.DecomposedAffine | None = None) -> [Component](#component)

Add a new component to the layer

Example:

component = layer.addComponent("A")
# With transformation matrix (legacy 6-element format converted to DecomposedAffine)
component = layer.addComponent("acutecomb", [1, 0, 0, 1, 250, 500])

insertShapeAt(index: float | int, shape: Babelfont.Shape) -> [Shape](#shape)

Insert a new shape at the specified index

splitOpenPathAtNode(pathOrIndex: float | int | [Shape](#shape) | [Path](#path), nodeIndex: float | int) -> { shapeIndex: number; insertedShapeIndex: number } | None

Split an open path into two open paths at an interior on-curve node.

connectOpenPathEndpoints(sourcePathOrIndex: float | int | [Shape](#shape) | [Path](#path), sourceEdge: 'start' | 'end', targetPathOrIndex: float | int | [Shape](#shape) | [Path](#path), targetEdge: 'start' | 'end') -> { shapeIndex: number; boundaryNodeIndex: number; closed: boolean; } | None

Connect two open-path endpoints or close a single open path by merging its endpoints.

removeShape(shapeOrIndex: float | int | [Shape](#shape) | [Path](#path) | [Component](#component)) -> None

Remove a shape at the specified index

addAnchor(x: float | int, y: float | int, name: str | None = None) -> [Anchor](#anchor)

Add a new anchor to the layer

Example:

anchor = layer.addAnchor(250, 700, "top")

addGuide(pos: Babelfont.Position, name: str | None = None, color: Babelfont.Color | None = None) -> [Guide](#guide)

removeAnchor(index: float | int) -> None

Remove an anchor at the specified index

removeGuide(index: float | int) -> None

processPathSegments(pathData: { nodes: Unsafe[]; closed?: boolean; }) -> Array<{ points: Array<{ x: number; y: number }>; type: 'line' | 'quadratic' | 'cubic'; }>

Process a path into Bezier curve segments Handles the babelfont node format where:

  • Nodes can have 'type' (lowercase: o, c, l, q, etc.) or 'nodetype' (capitalized: OffCurve, Curve, Line, etc.)
  • Segments are sequences: [oncurve] [offcurve*] [oncurve]
  • For closed paths, the path can start with offcurve nodes

getPathSegmentDescriptors(pathData: { nodes: Unsafe[]; closed?: boolean; }) -> Array<{ segmentId: number; type: 'line' | 'quadratic' | 'cubic'; points: Array<{ x: number; y: number }>; startNodeIndex: number; endNodeIndex: number; controlNodeIndices: number[]; runStartNodeIndex: number; runEndNodeIndex: number; runControlNodeIndices: number[]; segmentIndexInRun: number; wrapsAround: boolean; }>

calculatePathBounds(pathData: { nodes?: Unsafe[]; closed?: boolean; }) -> { minX: number; minY: number; maxX: number; maxY: number; width: number; height: number; } | None

calculateShapeBounds(shapes: list[Unsafe] | None, parentTransform: list[float | int]) -> { minX: number; minY: number; maxX: number; maxY: number; width: number; height: number; } | None

calculateSvgPathBounds(pathData: str) -> { minX: number; minY: number; maxX: number; maxY: number; width: number; height: number; } | None

getAllPaths() -> list[Babelfont.Path]

Get all paths in this layer including transformed paths from components (recursively flattened)

calculateBoundingBox(layerData: Unsafe, includeAnchors: bool, font: [Font](#font) | None = None, masterId: str | None = None) -> { minX: number; minY: number; maxX: number; maxY: number; width: number; height: number; } | None

Calculate bounding box for layer data

getBoundingBox(includeAnchors: bool) -> { minX: number; minY: number; maxX: number; maxY: number; width: number; height: number; } | None

Calculate bounding box for this layer

getIntersectionsOnLine(p1: { x: number; y: number }, p2: { x: number; y: number }, includeComponents: bool) -> Array<{ x: number; y: number; t: number }>

Calculate intersections between a line segment and all paths in this layer

getSidebearingsAtHeight(y: float | int) -> { left: number; right: number; } | None

Calculate sidebearings at a given Y height by measuring distance from glyph edges to first/last outline intersections

getMatchingLayerOnGlyph(glyphName: str) -> [Layer](#layer) | None

Find the exact matching stored layer on another glyph for this layer's effective designspace location.

toString() -> str


Shapelink

Shape wrapper that can contain either a Component or a Path

Access:

path = layer.paths[0]
shape = path.parent()

Methodslink

getPathSegment() -> list[(string | number)]

isComponent() -> bool

Check if this shape is a component

isPath() -> bool

Check if this shape is a path

asComponent() -> [Component](#component)

Get as Component (throws if not a component)

asPath() -> [Path](#path)

Get as Path (throws if not a path)

toString() -> str


Pathlink

Path (contour) in a layer

Access:

path = layer.paths[0]

Propertieslink

Read/Write Properties

  • nodes (list[Node])
  • closed (bool)
  • format_specific (dict | None)

Read-Only Properties

  • id (str | None): Stable identifier for CRDT addressing. Generated on load; preserved across edits.

Methodslink

getPathSegment() -> list[(string | number)]

insertNode(index: float | int, x: float | int, y: float | int, nodetype: Babelfont.NodeType, smooth: bool | None = None) -> [Node](#node)

Insert a node at the specified index

Example:

path.insertNode(1, 150, 250, "Line")  # Insert at index 1

removeNode(index: float | int) -> None

Remove a node at the specified index

Example:

path.removeNode(0)  # Remove first node

appendNode(x: float | int, y: float | int, nodetype: Babelfont.NodeType, smooth: bool | None = None) -> [Node](#node)

Append a node to the end of the path

Example:

path.appendNode(100, 200, "Line")
path.appendNode(300, 400, "Curve", smooth=True)

toString() -> str


Nodelink

Point in a path

Access:

node = path.nodes[0]

Propertieslink

Read/Write Properties

  • selected (bool): Whether this node is selected in the active outline editor.
  • x (float | int)
  • y (float | int)
  • nodetype (Babelfont.NodeType)
  • smooth (bool | None)

Read-Only Properties

  • id (str | None): Stable identifier for CRDT addressing. Generated on load; preserved across edits.

Methodslink

getPathSegment() -> list[(string | number)]

toString() -> str


Componentlink

Component reference to another glyph

Access:

component = layer.components[0]

Propertieslink

Read/Write Properties

  • selected (bool): Whether this component is selected in the active outline editor.
  • reference (str)
  • transform (Babelfont.DecomposedAffine)
  • location (DesignspaceLocation | None)
  • anchor (str | None): Glyphs attachment anchor name stored in format_specific.
  • automaticAlignment (bool): Whether this component explicitly opts into Glyphs automatic alignment. Unlike isAutomaticAligned(), this is per-component metadata and does not depend on the rest of its containing layer.
  • format_specific (dict | None)

Read-Only Properties

  • id (str | None): Stable identifier for CRDT addressing. Generated on load; preserved across edits.

Methodslink

getPathSegment() -> list[(string | number)]

isAutomaticAligned() -> bool

Returns whether every component in the containing layer explicitly opts into Glyphs automatic alignment.

hasExplicitManualAlignment() -> bool

Returns whether this component itself carries Glyphs' explicit manual alignment metadata, independent of the layer's effective state.

toAffineArray() -> list[float | int]

Convert transform to affine matrix array [a, b, c, d, e, f] Uses the proper DecomposedAffineTransform utility

toString() -> str

getTransformedPaths() -> list[Babelfont.Path]

Get all paths from this component with transforms applied recursively Automatically determines the correct master by walking up the parent chain


Anchorlink

Anchor point in a layer

Access:

anchor = layer.anchors[0]

Propertieslink

Read/Write Properties

  • selected (bool): Whether this anchor is selected in the active outline editor.
  • x (float | int)
  • y (float | int)
  • name (str | None)
  • format_specific (dict | None)

Read-Only Properties

  • id (str | None): Stable identifier for CRDT addressing. Generated on load; preserved across edits.

Methodslink

getPathSegment() -> list[(string | number)]

toString() -> str


Guidelink

Guideline in a layer or master

Access:

guide = layer.guides[0]
# or
guide = master.guides[0]

Propertieslink

Read/Write Properties

  • selected (bool): Whether this guide is selected in the active outline editor.
  • pos (Babelfont.Position)
  • name (str | None)
  • color (Babelfont.Color | None)
  • format_specific (dict | None)

Read-Only Properties

  • id (str | None): Stable identifier for CRDT addressing. Generated on load; preserved across edits.

Methodslink

getPathSegment() -> list[(string | number)]

toString() -> str


Axislink

Variation axis in a variable font

Access:

axis = font.axes[0]
# or
axis = font.findAxisByTag("wght")

Propertieslink

All properties are read/write:

  • name (dict[str, str])
  • tag (str)
  • id (str)
  • min (float | int | None)
  • max (float | int | None)
  • default (float | int | None)
  • map (list[[number, number]] | None)
  • hidden (bool | None)
  • values (list[float | int] | None)
  • format_specific (dict | None)

Methodslink

getPathSegment() -> list[(string | number)]

toString() -> str


Masterlink

Master/source in a design space

Access:

master = font.masters[0]
# or
master = font.findMaster("master-id")

Propertieslink

Read/Write Properties

  • name (dict[str, str])
  • id (str)
  • location (DesignspaceLocation | None)
  • metrics (dict)
  • kerning (dict)
  • kerning_rtl (dict)
  • custom_ot_values (list[Unsafe] | None)
  • format_specific (dict | None)

Read-Only Properties

  • guides (list[Guide] | None)

Methodslink

getPathSegment() -> list[(string | number)]

addGuide(pos: Babelfont.Position, name: str | None = None, color: Babelfont.Color | None = None) -> [Guide](#guide)

removeGuide(index: float | int) -> None

reinterpolateLayers() -> Promise<void>

delete() -> Promise<boolean>

toString() -> str


Instancelink

Named instance in a variable font

Access:

instance = font.instances[0]

Propertieslink

All properties are read/write:

  • id (str)
  • name (dict[str, str])
  • location (DesignspaceLocation | None)
  • custom_names (dict[str, dict[str, str] | None])
  • variable (bool | None)
  • linked_style (str | None)
  • format_specific (dict | None)

Methodslink

getPathSegment() -> list[(string | number)]

toString() -> str


Complete Exampleslink

Example 1: Creating a Simple Glyphlink

# Get the font
font = Font()

# Create a new glyph
glyph = font.addGlyph("myGlyph", "Base")

# Add a layer
layer = glyph.addLayer(500)  # 500 units wide

# Create a rectangle path
path = layer.addPath(closed=True)
path.appendNode(100, 0, "Line")
path.appendNode(400, 0, "Line")
path.appendNode(400, 700, "Line")
path.appendNode(100, 700, "Line")

print(f"Created glyph: {glyph.name}")

Example 2: Modifying Existing Glyphslink

font = Font()

# Find glyph A
glyph_a = font.findGlyph("A")
if glyph_a:
    layer = glyph_a.layers[0]
    
    # Modify all nodes
    for path in layer.paths:
        for node in path.nodes:
            node.x += 10  # Shift 10 units right
            node.y += 5   # Shift 5 units up
    
    # Add an anchor
    layer.addAnchor(250, 700, "top")
    
    print(f"Modified {glyph_a.name}")

Example 3: Working with Componentslink

font = Font()

# Create a glyph with a component
glyph = font.addGlyph("Aacute", "Base")
layer = glyph.addLayer(600)

# Add base letter component
base = layer.addComponent("A")

# Add accent component with transformation
# Transform: [scaleX, skewX, skewY, scaleY, translateX, translateY]
accent = layer.addComponent("acutecomb", [1, 0, 0, 1, 250, 500])

print(f"Created {glyph.name} with components")

Example 4: Iterating Through Fontlink

font = Font()

# Count nodes across all glyphs
total_nodes = 0
for glyph in font.glyphs:
    if glyph.layers:
        for layer in glyph.layers:
            for path in layer.paths:
                total_nodes += len(path.nodes)

print(f"Total nodes in font: {total_nodes}")

Example 5: Working with Variable Fontslink

font = Font()

# Check if font has axes
if font.axes:
    print("Variable font axes:")
    for axis in font.axes:
        print(f"  {axis.tag}: {axis.min} - {axis.max} (default: {axis.default})")
    
    # Check masters
    if font.masters:
        print(f"\nFont has {len(font.masters)} masters:")
        for master in font.masters:
            location_str = ", ".join(f"{k}={v}" for k, v in (master.location or {}).items())
            print(f"  Master: {location_str}")

Example 6: Batch Processing Glyphslink

font = Font()

# Scale all glyphs by 1.5x
scale_factor = 1.5

for glyph in font.glyphs:
    if glyph.layers:
        for layer in glyph.layers:
            # Scale width
            layer.width *= scale_factor
            
            # Scale all outline paths
            for path in layer.paths:
                for node in path.nodes:
                    node.x *= scale_factor
                    node.y *= scale_factor
            
            # Scale anchors
            if layer.anchors:
                for anchor in layer.anchors:
                    anchor.x *= scale_factor
                    anchor.y *= scale_factor

print(f"Scaled {len(font.glyphs)} glyphs by {scale_factor}x")

Example 7: Kerning and i18n Dictionarieslink

font = Font()
master = font.masters[0]

# Ensure nested kerning bucket exists
if "A" not in master.kerning:
    master.kerning["A"] = {}

master.kerning["A"]["V"] = -90
master.kerning["A"]["W"] = -70

# Read values with standard dict APIs
av_value = master.kerning["A"].get("V")
print(f"A/V kerning: {av_value}")

# Update localized names
font.names.familyName["dflt"] = "Counterpunch Sans"
font.names.familyName["de"] = "Counterpunch Sans DE"
font.names.familyName["fr"] = "Counterpunch Sans FR"
font.names.familyName["ar"] = "كاونتربنش سانس"

Example 8: Editing OpenType Features Listlink

font = Font()

# features is a live list-like wrapper
feature_items = font.features.features

# Append a new feature tuple: [tag, code-record]
feature_items.append(["liga", {"code": "sub f i by fi;"}])

# Insert at the top
feature_items.insert(0, ["kern", {"code": "pos A V -80;"}])

# Remove entries with normal list operations
if len(feature_items) > 5:
    feature_items.pop()

del feature_items[0]

Tips and Best Practiceslink

Performancelink

  • Changes to properties are immediately reflected in the underlying JSON data
  • No need to "save" or "commit" changes - they are live
  • Dictionary-like fields are live Python mappings (no routine .to_py() needed)
  • Array fields (for example font.features.features) are live list-like wrappers
  • For batch operations, group changes together to minimize redraws

Type Checkinglink

# Use the filtered convenience collections when you know what you want
for path in layer.paths:
    # Work with path

for component in layer.components:
    # Work with component

Safe Property Accesslink

# Check for optional properties
if glyph.layers:
    for layer in glyph.layers:
        for path in layer.paths:
            for node in path.nodes:
                print(f"Node at ({node.x}, {node.y})")

Guardrails for Dictionary Fieldslink

Dictionary-like fields reject scalar overwrite assignments to prevent broken model state.

# ❌ Avoid replacing a language dictionary with a string
# font.names.familyName = "My Font"

# ✅ Set a language value inside the dictionary
font.names.familyName["dflt"] = "My Font"

# ✅ Or replace with a full mapping
font.names.familyName = {
    "dflt": "My Font",
    "de": "Meine Schrift"
}

Accessing Nodes Examplelink

# Direct access (may fail if properties are None)
# glyph.layers[0].paths[0].nodes  # DON'T DO THIS

# Safe access with checks:
layer = glyph.layers[0] if glyph.layers else None
if layer and layer.paths:
    path = layer.paths[0]
    nodes = path.nodes
    print(f"Path has {len(nodes)} nodes")

Coordinate Systemlink

  • Origin (0, 0) is at the baseline on the left
  • Y-axis points upward
  • All coordinates are in font units (1/upm of the em square)

Common Issueslink

Q: Why does glyph.layers[0].paths[0].nodes fail?

A: Optional properties may be None. Use safe access:

# Check each step
if glyph.layers and len(glyph.layers) > 0:
    layer = glyph.layers[0]
    if layer.paths and len(layer.paths) > 0:
        path = layer.paths[0]
        nodes = path.nodes  # Now safe to access

Q: How do I access only paths or only components in a layer?

A: Use layer.paths and layer.components directly:

for path in layer.paths:
    print(len(path.nodes))

for component in layer.components:
    print(component.reference)

Generated by generate-api-docs.mjs