Manipulating Layer Data with Python in FontForge

Yes, you can fully manipulate layer data using Python in FontForge. FontForge provides robust Python bindings that expose both font-level layer definitions and individual glyph-level layer contents. This guide outlines how the layer architecture works, how to read and modify layer geometry directly, and how to programmatically transfer contours between different layers such as the Foreground and Background.

Understanding FontForge Layer Architecture

In FontForge, layers exist at two distinct levels:

  1. Font-Level Layers: Defined across the entire font, determining the layer names, spline types (Cubic or Quadratic), and whether a layer contains fill, stroke, or background data.
  2. Glyph-Level Layers: The actual vector contents (contours and references) present inside a specific glyph for a given layer.

FontForge accesses glyph layers primarily through the glyph.layers tuple or convenience properties like glyph.foreground and glyph.background.

Accessing Glyph Layers

Each element in glyph.layers is a fontforge.layer object containing contours and references. By default, index 0 corresponds to the Background layer and index 1 corresponds to the Foreground layer.

import fontforge

# Open font and select a glyph
font = fontforge.open("MyFont.sfd")
glyph = font["A"]

# Access via properties
fg_layer = glyph.foreground
bg_layer = glyph.background

# Access via index
first_layer = glyph.layers[0]

# Inspect contents
print(f"Number of contours in foreground: {len(fg_layer)}")

Modifying Layer Contours and Points

A fontforge.layer object acts like an iterable of fontforge.contour objects. To modify layer geometry, you extract the contours, alter their points, and assign the modified layer back to the glyph.

import fontforge

font = fontforge.open("MyFont.sfd")
glyph = font["A"]

# Retrieve the foreground layer
layer = glyph.foreground

# Shift every point in the layer horizontally by 50 units
for contour in layer:
    for point in contour:
        point.x += 50

# Reassign the layer back to the glyph to apply changes
glyph.foreground = layer
font.save()

When modifying points, changes are only committed to the font database once the layer is reassigned to glyph.foreground, glyph.background, or glyph.layers[index].

Copying Data Between Layers

A common task is duplicating geometry from one layer to another, such as backing up foreground outlines to the background before applying destructive transformations.

import fontforge

font = fontforge.open("MyFont.sfd")
glyph = font["A"]

# Copy foreground geometry to background
glyph.background = glyph.foreground.dup()

# Clear the foreground layer
glyph.foreground = fontforge.layer()

font.save()

Adding and Configuring Custom Layers

You can create custom layers at the font level using the font's layer configuration methods.

import fontforge

font = fontforge.open("MyFont.sfd")

# Check existing font layers
for name in font.layer_cnt:
    print(name)

# Enable multi-layer mode (needed for Type3 or SVG fonts with multiple colored layers)
font.multilayer = True

# Add a new cubic layer
new_layer_index = font.newLayer("Mask", False) # False indicates Cubic/PostScript

# Access the new layer inside a glyph
glyph = font["A"]
mask_layer = glyph.layers[new_layer_index]

Key Considerations

  • Layer Reassignment: Always reassign the layer object back to the glyph (e.g., glyph.layers[i] = layer) after altering its contours; in-place mutations of point coordinates inside a retrieved layer do not automatically update the underlying font database.
  • Coordinate Types: Coordinate values (x, y) accept floating-point numbers during manipulation, but PostScript and TrueType font export requirements will dictate final integer rounding.
  • References: If a layer contains component references (such as accents or composites), inspect layer.references in addition to contour iteration.