Skip to content

Instantly share code, notes, and snippets.

@connordavenport
Last active March 10, 2025 16:09
Show Gist options
  • Save connordavenport/ea50758429974d12df3d5c114d9d491b to your computer and use it in GitHub Desktop.
Save connordavenport/ea50758429974d12df3d5c114d9d491b to your computer and use it in GitHub Desktop.
draw custom metric guides in the glyph view
import math
from mojo.events import postEvent
from mojo.subscriber import Subscriber, registerGlyphEditorSubscriber, unregisterGlyphEditorSubscriber, listRegisteredSubscribers
from lib.tools.defaults import getDefault
from fontTools.misc import transform
border = getDefault("glyphViewVerticalPadding")
fontsize = getDefault("textFontSize")
metricsStroke = getDefault("glyphViewFontMetricsStrokeColor")
metricsText = getDefault("glyphViewMetricsTitlesColor")
KEY = "com.connordavenport.x_files"
'''
start up script to draw custom metric guides in the
glyph view using simple text syntax in the `font.info.note`.
lines need a preceeding underscore (_), metrics name, and value.
e.g.
_Small Caps: 510
_Superior Top: 715
_Inferior Bottom: -120
'''
class x_files(Subscriber):
debug = True
def build(self):
glyphEditor = self.getGlyphEditor()
self.container = glyphEditor.extensionContainer(
identifier=KEY,
location="background",
clear=True
)
self.glyph = glyphEditor.getGlyph()
def started(self):
self.draw_custom_metrics(self.glyph.font)
def destroy(self):
self.container.clearSublayers()
def glyphEditorDidSetGlyph(self, info):
self.glyph = info["glyph"]
font = self.glyph.font
self.draw_custom_metrics(font)
def glyphEditorFontInfoDidChange(self, info):
font = info["fontInfo"].font
self.draw_custom_metrics(font)
def get_values(self, font):
note = font.info.note
custom_metrics = {}
if note:
lines = note.split("\n")
for line in lines:
if line.strip().startswith("_"):
entry, value = line.split(":")
entry = entry.strip("_ ")
value = value.strip()
if value not in custom_metrics:
custom_metrics[value] = {
'displayvalue': None,
'names': []
}
custom_metrics[value]['displayvalue'] = value
custom_metrics[value]['names'].append(entry)
return custom_metrics
def draw_custom_metrics(self, font):
# based on benedikt bramböck's `ShowVMetrics` tool
self.container.clearSublayers()
custom_metrics = self.get_values(font)
postEvent(KEY + ".event", metrics=custom_metrics)
for value in custom_metrics:
all_names = f" {', '.join(custom_metrics[value]['names'])} ({custom_metrics[value]['displayvalue']})"
value = int(float(value))
self.container.appendLineSublayer(
startPoint=(-border*2, value),
endPoint=((self.glyph.width + border)*2, value),
strokeWidth=1,
strokeColor=(*metricsStroke[0:3],1),
)
# is there a better way to get the adjusted xPos??
off = font.lib.get('com.typemytype.robofont.italicSlantOffset', 0)
x = y = math.radians(-font.info.italicAngle or 0)
matrix = transform.Identity.skew(x=x, y=y)
t = transform.Transform()
oX, oY = (0,0)
t = t.translate(oX, oY)
t = t.transform(matrix)
t = t.translate(-oX, -oY)
trans = tuple(t)
ot = transform.Transform(*trans)
n = ot.transformPoint((self.glyph.width + off, value))
self.container.appendTextLineSublayer(
position=(n[0], value),
size=(20, 20),
weight="medium",
pointSize=fontsize,
text=all_names,
fillColor=metricsText,
horizontalAlignment="left",
verticalAlignment="bottom",
)
if __name__ == '__main__':
finder = [subs for subs in listRegisteredSubscribers() if 'x_files' in subs.getIdentifier()]
if finder:
for s in finder:
unregisterGlyphEditorSubscriber(s)
else:
print("registering x_files")
registerGlyphEditorSubscriber(x_files)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment