Skip to content

Instantly share code, notes, and snippets.

@frankrolf
Last active September 7, 2020 20:32
Show Gist options
  • Save frankrolf/ec914189f0ebb374217a3b7298f4e20e to your computer and use it in GitHub Desktop.
Save frankrolf/ec914189f0ebb374217a3b7298f4e20e to your computer and use it in GitHub Desktop.
Robofont observer to avoid writing fractional coordinates.
from mojo.events import addObserver
import mojo
VERSION = mojo.roboFont.version
class FloatObserver(object):
def __init__(self):
# addObserver(self, 'saveCallback', 'fontWillClose')
addObserver(self, 'saveCallback', 'fontWillSave')
def check_float_list(self, flat_list):
if(
any([isinstance(coord, float) for coord in flat_list])
):
return True
return False
def glyph_has_float_av(self, glyph):
# Check if the glyph in question has a .0 advance width.
if isinstance(glyph.width, float) and glyph.width == int(glyph.width):
return True
return False
def glyph_has_float_anchors(self, glyph):
# Check if the anchors have a .0 position.
anchors = [value for a in glyph.anchors for value in a.position]
if self.check_float_list(anchors):
return True
return False
def glyph_has_float(self, glyph):
# Check if the glyph has a float advance width,
# float point coordinates, or float component offsets.
if isinstance(glyph.width, float):
return True
points = [crd for c in glyph for p in c.points for crd in (p.x, p.y)]
components = [offset for c in glyph.components for offset in c.offset]
if self.check_float_list(points):
return True
if(
self.check_float_list(components) and
[int(v) for v in components] != components
):
return True
return False
def saveCallback(self, sender):
f = sender['font']
glyphOrder = f.glyphOrder
float_glyphs = [
gn for gn in glyphOrder if self.glyph_has_float(f[gn])]
float_av_glyphs = [
gn for gn in glyphOrder if self.glyph_has_float_av(f[gn])]
float_anchor_glyphs = [
gn for gn in glyphOrder if self.glyph_has_float_anchors(f[gn])]
# if any([float_glyphs, float_av_glyphs, float_anchor_glyphs]):
# print(f.info.familyName, f.info.styleName)
if float_glyphs:
print('float coords:', ' '.join(float_glyphs))
if float_av_glyphs:
print('float av:', ' '.join(float_av_glyphs))
if float_anchor_glyphs:
print('float anchors:', ' '.join(float_anchor_glyphs))
for gn in float_glyphs:
f[gn].round()
if VERSION.startswith('3'):
f[gn].changed()
else:
f[gn].update()
for gn in float_av_glyphs:
g = f[gn]
# weird: g.width = int(g.width) does not work.
old_width = int(g.width)
g.width = old_width + 1
g.width = old_width
for gn in float_anchor_glyphs:
g = f[gn]
for a in g.anchors:
old_x = int(round(a.x))
old_y = int(round(a.y))
a.x = old_x + 1
a.x = old_x
a.y = old_y + 1
a.y = old_y
print('Adding floatObserver.')
FloatObserver()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment