## Interpolating colors ``````'''Interpolating two RGB colors.'''

size(1000, 500)

# define two rgb colors
color1 = 0.5, 0.0, 0.3
color2 = 1.0, 0.6, 0.1

# total number of steps
steps = 12

# initial position
x, y = 0, 0

# calculate size for steps
w = width() / steps
h = height()

# iterate over the total amount of steps
for i in range(steps):

# calculate interpolation factor for this step
factor = i * 1.0 / (steps - 1)

# interpolate each rgb channel separately
r = color1 + factor * (color2 - color1)
g = color1 + factor * (color2 - color1)
b = color1 + factor * (color2 - color1)

# draw a rectangle with the interpolated color
fill(r, g, b)
stroke(r, g, b)
rect(x, y, w, h)

# increase x-position for the next step
x += w
``````

## Interpolating position and size ``````'''Interpolate position and size.'''

# define position and size for two rectangles
x1, y1 = 98, 88
w1, h1 = 480, 492

x2, y2 = 912, 794
w2, h2 = 20, 126

# total amount of steps
steps = 22

# define blend mode and color
blendMode('multiply')
fill(0, 0.3, 1, 0.2)

# iterate over the total amount of steps
for i in range(steps):

# calculate interpolation factor for this step
factor = i * 1.0 / (steps - 1)

# interpolate each rectangle attribute separately
x = x1 + factor * (x2 - x1)
y = y1 + factor * (y2 - y1)
w = w1 + factor * (w2 - w1)
h = h1 + factor * (h2 - h1)

# draw a rectangle with the calculated variables
rect(x, y, w, h)

``````

## Checking interpolation compatibility

Before interpolating two glyphs, we need to make sure that they are compatible. We can do that with code using a glyph’s `isCompatible` method. This function returns two values:

• The first is a boolean indicating if the two glyphs are compatible.
• If the first value is `False`, the second will contain a report of the problems.
``````f = CurrentFont()
g = f['O']
print(g.isCompatible(f['o']))
``````
``````(True, '')
``````
``````print(g.isCompatible(f['n']))
``````
``````(False, '[Fatal] Contour 0 contains a different number of segments.\n[Fatal] Contour 1 contains a different number of segments.\n[Warning] The glyphs do not contain components with exactly the same base glyphs.')
``````

## Interpolating glyphs in the same font ``````'''
Generate a number of interpolation and extrapolation steps between two selected glyphs in the current font.

'''

# settings
interpolationSteps = 5
extrapolateSteps = 2

# get the currentFont
f = CurrentFont()

if f is None:
# no font open
print("Oeps! There is not font open.")

else:
# get the selection
selection = f.selectedGlyphNames

# check if the selection contains only two glyphs
if len(selection) != 2:
print("Incompatible selection: two compatible glyphs are required.")

else:
# get the master glyphs
source1 = f[selection]
source2 = f[selection]

# check if they are compatible
if not source1.isCompatible(source2):
# the glyphs are not compatible
print("Incompatible masters: Glyph %s and %s are not compatible." % (source1.name, source2.name))

else:
# loop over the amount of required interpolations
nameSteps = 0
for i in range(-extrapolateSteps, interpolationSteps + extrapolateSteps + 1, 1):
# create a new name
name = "interpolation.%03i" % nameSteps
nameSteps += 1
# create the glyph if does not exist
dest = f.newGlyph(name)
# get the interpolation factor (a value between 0.0 and 1.0)
factor = i / float(interpolationSteps)
# interpolate between the two masters with the factor
dest.interpolate(factor, source1, source2)

# done!
f.changed()
``````

## Interpolating between two masters

``````'''
Interpolate glyphs from two master fonts into a third font.

The script expects 3 fonts open:

- the current font, where the glyphs will be interpolated
- one master font named “Regular”
- another master font named “Bold”

'''

# the font where the interpolated glyphs will be stored
f = CurrentFont()

# the two master fonts
f1 = AllFonts().getFontsByStyleName('Regular')
f2 = AllFonts().getFontsByStyleName('Bold')

# the interpolation factor
factor = 0.4

# a list of glyph names to be interpolated
glyphNames = ['A', 'B', 'C', 'a', 'b', 'c']

# iterate over the glyph names
for glyphName in glyphNames:

# if this glyph is not available in one of the masters, skip it
if not glyphName in f1:
print('%s not in %s, skipping…', (glyphName, f1))
continue
if not glyphName in f2:
print('%s not in %s, skipping…' % (glyphName, f1))
continue

# if the glyph does not exist in the destination font, create it
if not glyphName in f:
f.newGlyph(glyphName)

# interpolate glyph
print('interpolating %s…' % glyphName)
f[glyphName].interpolate(factor, f1[glyphName], f2[glyphName])
``````

## Interpolating fonts

``````'''Generate a new font by interpolating two master fonts.'''

# get fonts
font1 = OpenFont()
font2 = OpenFont()

# define interpolation factor
factor = 0.5

# make destination font
font3 = NewFont()

# this interpolates the glyphs
font3.interpolate(factor, font1, font2)

# this interpolates the kerning
# comment this line out of you're just testing
font3.kerning.interpolate(font1.kerning, font2.kerning, factor)

# done!
font3.changed()
``````

## Batch interpolating fonts

``````'''
Generate a series of instances by interpolating two master fonts.

The names and interpolation values of each instance are defined in a list of tuples.

'''

import os
from vanilla.dialogs import getFolder

# get masters and destination folder
font1 = OpenFont()
font2 = OpenFont()
folder = getFolder("Select a folder to save the interpolations")

# instance names and interpolation factors
instances = [
("Light", 0.25),
("Regular", 0.5),
("Bold", 0.75),
]

# generate instances
print('generating instances...\n')
for instance in instances:
styleName, factor = instance
print("\tgenerating %s (%s)..." % (styleName, factor))

# make a new font
dst = NewFont()

# interpolate the glyphs
dst.interpolate(factor, font1, font2)

# interpolate the kerning
# comment this line out of you're just testing
# dst.kerning.interpolate(font1.kerning, font2.kerning, value)

# set font name
dst.info.familyName = "MyFamily"
dst.info.styleName = styleName
dst.changed()

# save instance
fileName = '%s_%s.ufo' % (dst.info.familyName, dst.info.styleName)
ufoPath = os.path.join(folder, fileName)
print('\tsaving instances at %s...' % ufoPath)
dst.save(ufoPath)

# done with instance
dst.close()
print

print('...done.')
``````
``````generating instances...

generating Light (0.25)...
saving instances at /myFolder/MyFamily_Light.ufo...

generating Regular (0.5)...
saving instances at /myFolder/MyFamily_Regular.ufo...

generating Bold (0.75)...
saving instances at /myFolder/MyFamily_Bold.ufo...

...done.
``````

## Condensomatic ``````'''
Generate condensed glyphs from a Regular and a Bold.

Calculates a scaling factor from the Regular and Bold stem widths.

Uses interpolation and horizontal scaling to create condensed glyphs.

'''

# get Condensed, Regular and Bold fonts
condensedFont = CurrentFont()
regularFont = AllFonts().getFontsByStyleName('Roman')
boldFont = AllFonts().getFontsByStyleName('Bold')

# measure the Regular and Bold stem widths
regularStem = 95
boldStem = 140

# condensing factor
condenseFactor = 0.85

# calculate scale factor from stem widths
xFactor = float(regularStem) / (regularStem + condenseFactor * (boldStem - regularStem))

# interpolate selected glyphs
for glyphName in condensedFont.templateSelectedGlyphNames:

# get Condensed, Regular and Bold glyphs
condensedGlyph = condensedFont.newGlyph(glyphName, clear=True)
regularGlyph = regularFont[glyphName]
boldGlyph = boldFont[glyphName]

# interpolate Regular and Bold
condensedGlyph.clear()
condensedGlyph.interpolate((condenseFactor, 0), regularGlyph, boldGlyph)

# scale glyph horizontally
condensedGlyph.scaleBy((xFactor, 1))

# calculate glyph margins
condensedGlyph.leftMargin = (regularGlyph.leftMargin + boldGlyph.leftMargin) * 0.5 * (1.0 - condenseFactor)
condensedGlyph.rightMargin = (regularGlyph.rightMargin + boldGlyph.rightMargin) * 0.5 * (1.0 - condenseFactor)

# done!
condensedGlyph.changed()
``````
Last edited on 28/01/2019