Skip to content

Instantly share code, notes, and snippets.

@okay-type
Last active April 5, 2021 17:50
Show Gist options
  • Save okay-type/3d15b8aab357cb709adcd53fa8032321 to your computer and use it in GitHub Desktop.
Save okay-type/3d15b8aab357cb709adcd53fa8032321 to your computer and use it in GitHub Desktop.
quick and dirty udpate of addoverlap with ui for robofont 4
from vanilla import *
from mojo.UI import CurrentGlyphWindow
from mojo.events import addObserver, removeObserver
from mojo.subscriber import Subscriber, registerGlyphEditorSubscriber
from merz import *
from AppKit import NSColor, NSTextAlignmentRight, NSTextAlignmentLeft
from fontTools.ufoLib.pointPen import AbstractPointPen
from mojo.extensions import setExtensionDefault, getExtensionDefault, registerExtensionDefaults
import math
import re
'''
quick and dirty udpate of addoverlap with ui for robofont 4
big changes:
this never really made sense as a toolbar button
it should probably be a contextual menu option
but i didnt want to figure out how to build one of those for glyph edit window
instead I simply added a button and an edittext field to to bottom Status Bar
next:
needs to be tested for bugs
'''
class CustomGlyphWindowDisplayMenu(Subscriber):
debug = False
def build(self):
self.name = self.__class__.__name__
if self.debug == True:
print(self.name, 'build!')
self.prefKey = 'com.okaytype.addOverlap'
initialDefaults = {
self.pref: '30'}
registerExtensionDefaults(initialDefaults)
self.toolValue = getExtensionDefault(self.pref)
self.bar = self.getGlyphEditor().getGlyphStatusBar()
self.addOverlapUI()
def destroy(self):
if self.debug == True:
print(self.name, 'destroy!')
setExtensionDefault(self.prefKey + '.addOverlapValue', self.ui.menuEditNo.get())
if hasattr(self.bar, 'overlapUI'):
del self.bar.overlapUI
@property
def pref(self):
return self.prefKey + '.' + 'addOverlapValue'
# def glyphEditorDidOpen(self, info):
# if self.debug == True:
# print(self.name, 'glyphEditorDidOpen!')
# def glyphEditorDidSetGlyph(self, info):
# if self.debug == True:
# print('glyphEditorDidSetGlyph!')
# self.addOverlapUI()
def addOverlapUI(self):
self.bar.overlapUI = Group((125, 0, 100, -1))
self.ui = self.bar.overlapUI
self.ui.menuButton = Button((0, 0, 25, -0), '⋉', callback=self.addOverlap)
self.ui.menuEditNo = EditText((23, 3, -0, -0), self.toolValue, sizeStyle='small', callback=self.editTextCallback)
t = self.ui.menuEditNo.getNSTextField()
t.setBezeled_(False)
t.setBackgroundColor_(NSColor.clearColor())
b = self.ui.menuButton.getNSButton()
b.setBezelStyle_(7)
b.setToolTip_('Add Overlap to Selected Points')
def editTextCallback(self, sender):
self.toolValue = self.onlynumbers(sender.get())
if len(self.toolValue) > 0 and self.toolValue[-1] != '-':
sender.set(self.toolValue)
# setExtensionDefault(self.prefKey + '.addOverlapValue', self.toolValue)
def onlynumbers(self, v):
v = v.replace(' ', '')
if v is None or v == '':
v = '0'
if v == '-0':
v = '0'
negpos = ''
if v[0] and v[0] == '-' and v != '0':
negpos = '-'
v = negpos + re.sub(r'[-\D]', '', v)
return v
def addOverlap(self, sender):
offset = self.toolValue
if self.toolValue == '':
offset = 0
g = CurrentGlyph()
selection = []
for p in g.selectedPoints:
p.selected = False
selection.append((p.x, p.y))
pen = AddOverlapPointPen(selection, offset)
g.drawPoints(pen)
g.prepareUndo('addOverlap')
g.clearContours()
pen.drawPoints(g.getPointPen())
g.performUndo()
g.changed()
def getLength(pt1, pt2):
x1, y1 = pt1
x2, y2 = pt2
return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
def pointOnACurve(curve, value):
(x1, y1), (cx1, cy1), (cx2, cy2), (x2, y2) = curve
dx = x1
cx = (cx1 - dx) * 3.0
bx = (cx2 - cx1) * 3.0 - cx
ax = x2 - dx - cx - bx
dy = y1
cy = (cy1 - dy) * 3.0
by = (cy2 - cy1) * 3.0 - cy
ay = y2 - dy - cy - by
mx = ax * (value)**3 + bx * (value)**2 + cx * (value) + dx
my = ay * (value)**3 + by * (value)**2 + cy * (value) + dy
return mx, my
class AddOverlapPointPen(AbstractPointPen):
def __init__(self, selectedPoints=[], offset=30):
self.offset = int(offset)
self.selectedPoints = selectedPoints
self._contours = []
self._components = []
def beginPath(self):
self._contours.append([])
self.firstSegment = None
self.prevOncurve = None
def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs):
data = dict(point=pt, segmentType=segmentType, smooth=smooth, name=name, kwargs=kwargs)
self._contours[-1].append(data)
def endPath(self):
pass
def addComponent(self, baseGlyphName, transformation):
pass
def _offset(self, pt1, pt2):
x1, y1 = pt1
x2, y2 = pt2
length = getLength((x1, y1), (x2, y2))
if length == 0:
return 0, 0
ox = (x2 - x1) / length * self.offset
oy = (y2 - y1) / length * self.offset
return int(round(ox)), int(round(oy))
def drawPoints(self, outpen):
for pointsData in self._contours:
if len(pointsData) == 1:
# ignore single movetos and anchors
continue
outpen.beginPath()
lenPointsData = len(pointsData)
for i, pointData in enumerate(pointsData):
currentPoint = pointData["point"]
addExtraPoint = None
if pointData["segmentType"] and pointData["point"] in self.selectedPoints:
prevPointData = pointsData[i - 1]
nextPointData = pointsData[(i + 1) % lenPointsData]
prevOffsetX, prevOffsetY = self._offset(prevPointData["point"], pointData["point"])
nextOffsetX, nextOffsetY = self._offset(pointData["point"], nextPointData["point"])
if (nextOffsetX, nextOffsetY) == (0, 0) and nextPointData["segmentType"] is None:
nextSegment = [
pointsData[(i + 3) % lenPointsData]["point"],
pointsData[(i + 2) % lenPointsData]["point"],
nextPointData["point"],
pointData["point"]]
newPoint = pointOnACurve(nextSegment, 0.9)
nextOffsetX, nextOffsetY = self._offset(pointData["point"], newPoint)
addExtraPoint = currentPoint[0] - nextOffsetX, currentPoint[1] - nextOffsetY
if (prevOffsetX, prevOffsetY) == (0, 0) and prevPointData["segmentType"] is None:
prevSegment = [
pointsData[i - 3]["point"],
pointsData[i - 2]["point"],
prevPointData["point"],
pointData["point"]]
newPoint = pointOnACurve(prevSegment, 0.9)
prevOffsetX, prevOffsetY = self._offset(newPoint, pointData["point"])
currentPoint = currentPoint[0] + prevOffsetX, currentPoint[1] + prevOffsetY
outpen.addPoint(
currentPoint,
pointData["segmentType"],
pointData["smooth"],
pointData["name"],
**pointData["kwargs"])
if addExtraPoint:
outpen.addPoint(addExtraPoint, "line")
outpen.endPath()
for baseGlyphName, transformation in self._components:
outpen.addComponent(baseGlyphName, transformation)
registerGlyphEditorSubscriber(CustomGlyphWindowDisplayMenu)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment