Skip to content

Instantly share code, notes, and snippets.

@okay-type
Last active November 3, 2021 22:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save okay-type/cffaf9bdc56d7b578be1d42d68af650a to your computer and use it in GitHub Desktop.
Save okay-type/cffaf9bdc56d7b578be1d42d68af650a to your computer and use it in GitHub Desktop.
MM-quick-compare-kerning.py
import metricsMachine as mm
from vanilla import *
from mojo.events import addObserver, removeObserver, postEvent
from mojo.UI import GetFile
import merz
from fontTools.pens.basePen import BasePen
# this update lets you do basic edits to the current kern value
def _getMainWindowControllerForFont(font=None):
if font is None:
font = CurrentFont()
for other in AllFonts():
if other != font:
continue
document = other.document()
for controller in document.windowControllers():
window = controller.window()
if hasattr(window, "windowName") and window.windowName() == "MetricsMachineMainWindow":
delegate = window.delegate()
mmController = delegate.vanillaWrapper()
return mmController
raise MetricsMachineScriptingError("A MetricsMachine window is not open for %r." % font)
class DecompPen(BasePen):
def __init__(self, glyphSet, outPen):
super(DecompPen, self).__init__(glyphSet)
self._moveTo = outPen.moveTo
self._lineTo = outPen.lineTo
self._curveToOne = outPen.curveTo
self._closePath = outPen.closePath
self._endPath = outPen.endPath
class mmComparison():
def __init__(self):
ufo = GetFile(
message=None,
title=None,
directory=None,
fileName=None,
allowsMultipleSelection=False,
fileTypes=None
)
self.compare = OpenFont(ufo, showUI=False)
self.w = Window(
(0, 0, 1000, 200),
'Compare Kerning',
fullSizeContentView=True,
titleVisible=False,
)
self.w.merzview = merz.MerzView(
(0, 0, -0, -0),
backgroundColor=(1, 1, 1, 1)
)
self.w.edit = EditText(
(-200, 0, 100, 22),
placeholder='0',
continuous=False,
callback=self.edit,
)
self.w.save = Button(
(-100, 0, 100, 22),
title='Save',
callback=self.save,
)
self.w.save.enable(False)
self.fillGlyph = (0, 0, 0, 1)
self.num = (0, 0, 0, .05)
self.numP = (0, .7, .6, 1)
self.numN = (1, 0, 0, 1)
addObserver(self, 'pairChanged', 'MetricsMachine.currentPairChanged')
self.w.bind('close', self.close)
self.w.open()
self.pairChanged(None)
def getMMGlyphs(self):
names = []
pairView = _getMainWindowControllerForFont().editView.pairView
for g in pairView.getPairView().getGlyphs():
names.append(g.name)
return names, pairView.getPointSize()
def close(self, sender):
self.compare.close()
removeObserver(self, 'MetricsMachine.currentPairChanged')
def edit(self, sender):
newKern = sender.get()
self.w.save.enable(True)
pairCurrent = left, right = list(mm.GetCurrentPair())
currentKern = str(self.compare.kerning.find(pairCurrent))
# update kerning here
# check if that should be a group instead of a glyph
matching = [s for s in self.compare.groups.findGlyph(left) if 'public.kern1' in s]
if len(matching) > 0:
left = matching[0]
# check if that should be a group instead of a glyph
matching = [s for s in self.compare.groups.findGlyph(right) if 'public.kern2' in s]
if len(matching) > 0:
right = matching[0]
if newKern == '0' or newKern == '' or newKern == 'None':
self.compare.kerning.remove((left, right))
print('Removing ', left, right, 'kern from comparison ufo')
else:
self.compare.kerning[(left, right)] = int(newKern)
print('Adding ', left, right, newKern, 'kern to comparison ufo. Don\'t forget to save')
# update
self.pairChanged(None)
def save(self, sender):
self.w.save.enable(False)
self.compare.save()
print('Saved comparison ufo to', self.compare.path)
def pairChanged(self, notification):
pairCurrent = list(mm.GetCurrentPair())
currentKern = str(self.compare.kerning.find(pairCurrent))
if currentKern == 'None':
currentKern = '0'
self.w.edit.set(currentKern)
# self.pairCurrent = notification['pair']
glyphs, size = self.getMMGlyphs()
x = shift = 0
scale = size / 1000
view = self.w.merzview
container = view.getMerzContainer()
container.clearSublayers()
container.setContainerScale(scale)
layerPreview = container.getSublayer('layerPreview')
if layerPreview is None:
layerPreview = container.appendBaseSublayer(
name='layerPreview',
position=(300, dict(point='center', offset=-100)),
size=(view.width(), view.height()),
)
with layerPreview.drawingTools() as bot:
for i, glyphName in enumerate(glyphs):
if glyphName in self.compare.glyphOrder:
if (x+self.compare[glyphName].width+400)*scale < view.width():
if shift != 0 and i != 0:
if glyphName != 'space' and glyphs[i-1] != 'space':
c = self.num
if shift < 0: c = self.numN
if shift > 0: c = self.numP
textLineLayer = layerPreview.appendTextLineSublayer(
position=(x, -500),
size=(10, 10),
pointSize=9,
text=str(shift),
fillColor=(*c,),
horizontalAlignment='center'
)
bot.fill(*self.fillGlyph,)
rglyph, x = self.getGlyph(glyphName, x)
bot.drawGlyph(rglyph)
if i < len(glyphs)-1:
shift = self.compare.kerning.find((glyphName, glyphs[i+1]))
if shift == None:
shift = 0
x += shift
def getGlyph(self, glyph, x, layer=None):
if glyph == 'space':
return self.compare[glyph], self.compare[glyph].width + x
else:
g = self.compare[glyph]
rglyph = RGlyph()
pen = DecompPen(self.compare, rglyph.getPen())
g.draw(pen)
rglyph.moveBy((x, 0))
x += g.width
return rglyph, x
mmComparison()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment