Building accented glyphs with a script ↩
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)