Doing things to fonts ↩
- Set fixed width in all glyphs
- Modify existing font info
- Set infos in all open fonts
- Copy font infos from one font to another
- Batch generate fonts for all UFOs in folder
- Import a font into a layer of the current font
- Building accented glyphs
- Scale a font
A collection of simple scripts to do things to fonts.
Set fixed width in all glyphs
Set a fixed width in all glyphs in the current font.
# get the current font
font = CurrentFont()
# iterate over all glyphs in the font
for glyph in font:
# set glyph width
glyph.width = 400
Set a fixed width in all selected glyphs in the current font. Enable undo/redo.
# define a width value
value = 400
# get the current font
font = CurrentFont()
# iterate over all selected glyphs in the font
for glyph in font.selectedGlyphs:
# wraps the glyph width change in an undo context
with glyph.undo():
# set glyph width
glyph.width = value
Modify existing font info
Setting a font info is as easy as setting a value. The new value will override the old one.
# get the current font
font = CurrentFont()
# edit some font info
font.info.familyName = "My Font"
font.info.ascender = 650
font.info.openTypeOS2Selection = [2, 4]
If you need to modify a mutable container, like adding a bit flag to the openTypeOS2Selection
, be aware that you cannot modify it in-place. To update the Info
object, the new value needs to be set, as in this example:
# get the current font
font = CurrentFont()
# set
font.info.openTypeOS2Selection = [2, 4]
# get
selection = font.info.openTypeOS2Selection
# edit
selection.append(8)
# reset
font.info.openTypeOS2Selection = selection
print(font.info.openTypeOS2Selection)
# >>> [2, 4, 8]
Set infos in all open fonts
Set font infos from a dictionary into all open fonts.
# a dictionary with font infos
infoDict = {
# attribute : data,
'openTypeNameDesigner' : 'Claude Garamond',
'year' : 1532,
'copyright' : 'Copyright (c) 1532 Claude Garamond.',
'note' : 'bonjour le monde',
}
# for each open font
for font in AllFonts():
# iterate over all attributes and values
for attr, value in infoDict.items():
# set font info data
setattr(font.info, attr, value)
# done!
Copy font infos from one font to another
Copy font info data from one open font to another.
# get the source font by name
f1 = AllFonts().getFontsByStyleName('Regular')[0]
# get the target font by name
f2 = AllFonts().getFontsByStyleName('Bold')[0]
# a list of font.info attributes to copy
attributes = [
'familyName',
'xHeight',
'openTypeNameDesigner',
]
# copy font.info data from f1 to f2
for attr in attributes:
# get value from source font
value = getattr(f1.info, attr)
# set value in target font
setattr(f2.info, attr, value)
Batch generate fonts for all UFOs in folder
Batch generate OTFs from a folder of UFOs.
- open a dialog to select a folder
- open each UFO in folder (without the UI)
- generate OpenType-CFF font from UFO
import os
from vanilla.dialogs import getFolder
# select folder
folder = getFolder('Select a folder with UFOs')[0]
# iterate over all files in folder
for f in os.listdir(folder):
# skip files which are not .ufos
if os.path.splitext(f)[-1] != '.ufo':
continue
# get full ufo path
ufoPath = os.path.join(folder, f)
# open ufo (without UI) # use 'showUI' in RF 1.8
font = OpenFont(ufoPath, showInterface=False)
# make otf path
otfPath = ufoPath.replace('.ufo', '.otf')
# generate otf font
font.generate(path=otfPath, format='otf', decompose=True, checkOutlines=True, releaseMode=True)
# close the ufo
font.close()
Import a font into a layer of the current font
Import glyphs from a second font into a layer of the current font.
# get the current font
font1 = CurrentFont()
# open a second font (without the UI)
font2 = OpenFont(showInterface=False)
# create target layer
layerName = f"{font2.info.familyName} {font2.info.styleName}"
dstLayer = font1.newLayer(layerName)
# loop over all glyphs in the second font
for glyph in font2:
# add the glyph to the layer
dstLayer[glyph.name] = glyph
# done!
Building accented glyphs
Build accented glyphs in RoboFont3 using Glyph Construction.
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()
Build accented glyphs in RoboFont1 using RoboFab’s font.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)
Scale a font
Scale different types of data in a font:
- glyph contours and metrics
- anchors
- font guides and glyph guides
- kerning
- font dimensions
font = CurrentFont()
newUpm = 100
oldUpm = font.info.unitsPerEm
factor = newUpm / oldUpm
for layer in font.layers:
for glyph in layer:
for contour in glyph:
contour.scaleBy(factor)
for anchor in glyph.anchors:
anchor.scaleBy(factor)
for guideline in glyph.guidelines:
guideline.scaleBy(factor)
glyph.width *= factor
font.kerning.scaleBy(factor)
for guideline in font.guidelines:
guideline.scaleBy(factor)
for attr in ['unitsPerEm', 'descender', 'xHeight', 'capHeight', 'ascender']:
oldValue = getattr(font.info, attr)
newValue = oldValue * factor
setattr(font.info, attr, newValue)
font.changed()