UFO

Glyphs uses its own .glyphs file format to store font sources, and supports UFO as a data interchange format: UFOs can be opened and saved as a native format, and there’s a built-in UFO export function.

The Glyphs documentation includes a tutorial on Working with UFOs. This page provides additional information for RoboFont users.

Notes about exporting UFOs from Glyphs

  1. When exporting UFOs using the Export to UFO menu, only the current front font is exported – active instances in files with multiple sources are not included. Use the script below if you need to export UFOs from all instances.

  2. Fonts are exported to UFO2 format; UFO3 is not supported yet.

  3. All glyphs are exported, including those marked to not export. You‘ll have to take care of removing them later.

  4. The following private keys are added to the UFO’s font lib:

    • com.schriftgestaltung.font.license
    • com.schriftgestaltung.font.licenseURL
    • com.schriftgestaltung.font.panose
    • com.schriftgestaltung.disablesAutomaticAlignment
    • com.schriftgestaltung.glyphOrder
    • com.schriftgestaltung.useNiceNames
    • com.schriftgestaltung.fontMasterID
  5. Mark colors are lost when opening exported UFOs in RoboFont 1; they work fine in RoboFont 3.

Exporting UFOs with code

Using glyphsLib

GoogleFonts developed the glyphsLib Python module that provides a bridge from Glyphs source files to UFOs and Designspace files.

Export all open fonts to UFO

This script exports the front source of all open fonts to UFO.

# MenuTitle: batch ufo export
# -*- coding: utf-8 -*-

__doc__ = """Export all open fonts to ufo"""

import os.path

Exporter = NSClassFromString('GlyphsFileFormatUFO').alloc().init()

for f in Glyphs.fonts:
    Master = f.fontMasters()[0]
    Exporter.setFontMaster_(Master)
    filePath = f.parent.fileURL().path()
    # TODO: make a folder called 'ufo' and save the ufos there
    fileName, folderName = os.path.basename(filePath), os.path.dirname(filePath)
    ufoFolder = os.path.join(folderName, 'ufo')
    ufoFileName = fileName.replace('.glyphs', '.ufo')

    if not os.path.exists(ufoFolder):
        os.mkdir(ufoFolder)

    ufoFilePath = os.path.join(ufoFolder, ufoFileName)
    Result = Exporter.writeUfo_toURL_error_(f, NSURL.fileURLWithPath_(ufoFilePath), None)

# open folder where the ufo files were saved
import os
os.system("open %s" % ufoFolder)

Export all instances to UFO

This script exports all instances in the current font to UFO.

# MenuTitle: export instances to UFO
# -*- coding: utf-8 -*-

"""
Export all instances from the current Glyphs.app font to UFO.
It saves the UFO file in the same folder as the source files.

"""

import os
import subprocess

ufoExporter = Glyphs.objectWithClassName_("GlyphsFileFormatUFO")
font = Glyphs.font
fontFilePath = font.filepath

for instance in Glyphs.font.instances:
    if not instance.active:
        continue
    instanceFont = instance.interpolatedFont
    ufoExporter.setFontMaster_(instanceFont.masters[0])
    folder = os.path.dirname(font.filepath)
    ufoFilePath = os.path.join(folder, '%s-%s.ufo' % (font.familyName, instance.name))
    dest = NSURL.fileURLWithPath_(ufoFilePath)
    ufoExporter.writeUfo_toURL_error_(instanceFont, dest, None)

subprocess.Popen(['open', folder])

Opening UFOs in Glyphs

Some data might be lost by editing a UFO file with Glyphs. The list of issues can change over time, so the conditional is mandatory. If you know of any other piece of data lost during the process, please let us know. Here is a list of the known issues:

  • The template glyph order is lost
  • Glyphs convert all non-kerning groups to feature class definition

Based on original contribution by Joancarles Casasín.

Last edited on 01/09/2021