Using GlyphConstruction

RoboFont 3 comes with the glyphConstruction module embedded, so you can import it into a script and build glyphs from glyph construction rules.

from glyphConstruction import ParseGlyphConstructionListFromString, GlyphConstructionBuilder

# define glyph constructions
txt = '''\
?agrave = a + grave@center,top
aacute = a + acute@center,top
'''

# get the actual glyph constructions from text
constructions = ParseGlyphConstructionListFromString(txt)

# get the current font
font = CurrentFont()

# collect glyphs to ignore if they already exist in the font
ignoreExisting = [L.split('=')[0].strip()[1:] for L in txt.split('\n') if L.startswith('?')]

# iterate over all glyph constructions
for construction in constructions:

    # build a construction glyph
    constructionGlyph = GlyphConstructionBuilder(construction, font)

    # if the construction for this glyph was preceded by `?`
    # and the glyph already exists in the font, skip it
    if constructionGlyph.name in font and constructionGlyph.name in ignoreExisting:
        continue

    # get the destination glyph in the font
    glyph = font.newGlyph(constructionGlyph.name, clear=True)

    # draw the construction glyph into the destination glyph
    constructionGlyph.draw(glyph.getPen())

    # copy construction glyph attributes to the destination glyph
    glyph.name = constructionGlyph.name
    glyph.unicode = constructionGlyph.unicode
    glyph.width = constructionGlyph.width
    glyph.markColor = 1, 1, 0, 0.5

    # if no unicode was given, try to set it automatically
    if glyph.unicode is None:
        glyph.autoUnicodes()

Using compileGlyph (RF1)

In RoboFont 1, you could build accented glyphs using RoboFab’s RFont.compileGlyph.

# get current font
font = CurrentFont()

# a dictionary of glyph constructions
accentsDict = {
    # accented glyph : [base glyph, [(accent, anchor)]],
    'agrave' : ['a', [('grave', 'top')]],
    'aacute' : ['a', [('acute', 'top')]],
    # ...add more accented glyphs here...
}

# iterate over all accented glyphs
for accentedGlyph in accentsDict.keys():

    # get base glyph and accents/anchors
    baseGlyph, accents = accentsDict[accentedGlyph]

    # build accented glyph using components
    font.compileGlyph(accentedGlyph, baseGlyph, accents)

Upgrading from compileGlyph to glyphConstruction

If you are upgrading from RoboFont 1 to RoboFont 3, you can use the script below to convert your accents data into a string of glyph constructions.

'''accentsDict2GlyphConstruction'''

#: A dictionary with data for building accented glyphs, as typically used with RoboFab's RFont.compileGlyph()
accentsDict = {
    # accented   : [ base, ( (accent1, anchor1), (accent2, anchor2), ... ) ],
    'aogonek'    : [ 'a',  ( ('ogonek', 'bottom'), ) ],
    'agrave'     : [ 'a',  ( ('grave', 'top'), ) ],
    'ccedilla'   : [ 'c',  ( ('cedilla', 'bottom'), ) ],
    'aringacute' : [ 'a',  ( ('ring', 'top'), ('acute', 'top'), ) ],
}

def accentsDict2GlyphConstruction(accentsDict, useSpaces=True):
    '''Converts glyph building recipes from dictionary to Glyph Construction syntax.'''

    # create an empty string to collect all GlyphConstruction rules
    glyphConstruction = ''

    # iterate over the accented glyphs dict
    for accentedGlyph in accentsDict:

        # get base glyph and accents for this accented glyph
        baseGlyph, accents = accentsDict[accentedGlyph]

        # start a glyph construction rule for this glyph:
        # accentedGlyph = baseGlyph + (some accents)
        glyphConstruction += '%s = %s + ' % (accentedGlyph, baseGlyph)

        # iterate over all accents in accented glyph, using a counter
        for i, (accentName, anchor) in enumerate(accents):
            # if accent is not the first, add a '+' before it
            if not i == 0:
                glyphConstruction += ' + '
            # add accent name and anchor name to glyph construction rule
            glyphConstruction += '%s@%s' % (accentName, anchor)

        # done with this accented glyph; go to the next line
        glyphConstruction += '\n'

    # remove all spaces
    if not useSpaces:
        glyphConstruction = glyphConstruction.replace(' ', '')

    # done!
    return glyphConstruction

# convert accents dict to glyph construction
glyphConstruction = accentsDict2GlyphConstruction(accentsDict, useSpaces=False)
print(glyphConstruction)
Last edited on 01/09/2021