Skip to content

Instantly share code, notes, and snippets.

@LettError
Created October 25, 2017 14:33
Show Gist options
  • Save LettError/c1e76a8011df67684bb964c498d2a328 to your computer and use it in GitHub Desktop.
Save LettError/c1e76a8011df67684bb964c498d2a328 to your computer and use it in GitHub Desktop.
A comparison between the way MathKerning and Batch interpolate kerning
# an exploration of the issue described in
# https://github.com/typemytype/batchRoboFontExtension/issues/25
# erik@letterror.com
# October 25 2017
from pprint import pprint
from fontMath.mathKerning import MathKerning
from mutatorMath.objects.mutator import buildMutator, Location
dA = {("first", "second"):-10, ("firstControl", "secondControl"):-10}
print dA
dB = {("first", "second"):-15, ("firstControl", "secondControl"):-15}
print dB
dC = {("first", "second"):0,}
print dC
mA = MathKerning(dA)
mB = MathKerning(dB)
mC = MathKerning(dC)
print mA, mB, mC
# # # # # # # Step 1: Superpolator / MathKerning
# Superpolator uses the mathKerning object to represent entire kerning sets for a master.
# first, build a mutator with these whole dictionaries
# test locations along the "kern" axis. No, I'm not proposing a "kern" axis. This is just for this test.
lA = Location(kern=0)
lB = Location(kern=100)
lC = Location(kern=200)
items = [
(lA, mA),
(lB, mB),
(lC, mC),
]
bias, mt = buildMutator(items)
# let's see what it brings.
# as expected, results at lA
print "results at kern=0", sorted(mt.makeInstance(Location(kern=0)).items())
assert sorted(mt.makeInstance(Location(kern=0)).items()) == [(('first', 'second'), -10), (('firstControl', 'secondControl'), -10)]
# as expected, results at lB
print "results at kern=100", sorted(mt.makeInstance(Location(kern=100)).items())
assert sorted(mt.makeInstance(Location(kern=100)).items()) == [(('first', 'second'), -15), (('firstControl', 'secondControl'), -15)]
# results at interpolation between lB and lC
print "results at kern=150", sorted(mt.makeInstance(Location(kern=150)).items())
assert sorted(mt.makeInstance(Location(kern=150)).items()) == [(('first', 'second'), -7.5), (('firstControl', 'secondControl'), -7.5)]
# when we get closer to the 200, we can see the values getting smaller.
print sorted(mt.makeInstance(Location(kern=199)).items())
assert sorted(mt.makeInstance(Location(kern=199)).items()) == [(('first', 'second'), -0.15000000000000036), (('firstControl', 'secondControl'), -0.15000000000000036)]
# at location lC, both pairs have become 0 and mathkerning has already cleaned up the dict.
print sorted(mt.makeInstance(Location(kern=200)).items())
assert sorted(mt.makeInstance(Location(kern=200)).items()) == []
# # # # # # # Step 2: Batch / MutatorMath
# Batch has a different problem to solve. It needs prepare a matching table for each pair in all masters.
# It creates this table by processing each pair. Let's use the pairs in dA, in Batch this would be the superset
# of all kerning in all masters.
allMasters = [dA, dB, dC]
thisItem = []
# the following is a paraphrase of what Batch does here:
# Reference https://github.com/typemytype/batchRoboFontExtension/blob/d59262e8a17f38ce385b542c8c5f7962f07e03f4/Batch.roboFontExt/lib/variableFontGenerator/__init__.py#L412
testPair = ("firstControl", "secondControl")
if testPair in dA:
thisItem.append((lA, dA.get(testPair)))
# yes this one exists
if testPair in dB:
thisItem.append((lB, dB.get(testPair)))
# yes this one exists as well
if testPair in dC:
thisItem.append((lC, dC.get(testPair)))
# no, this one does not exist
# So when we look at the items for this interpolation we get this:
assert thisItem == [(lA, -10), (lB, -15)]
print "items for this pairs interpolation",testPair, thisItem
# Note: dC did not have the testpair, so there was no value-, so the pair is not added.
bias, m2 = buildMutator(thisItem)
print m2
assert m2.makeInstance(lA) == -10
assert m2.makeInstance(lB) == -15
# that leads to this counterintuitive result:
print m2.makeInstance(lC) == -20
# rather than the "0" that the mathKerning brings.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment