Constrain angle tool ↩
This example shows a custom EditingTool which uses the font’s italic angle to constrain point movements – a useful tool when working on slanted designs.
The tool subclasses EditingTool._mouseDragged
and disables its Shift constraint, before adding its own Shift behaviour.
Off-curve points are constrained in relation to their on-curve point, not the last mouse down point.
from math import tan, radians
from mojo.events import EditingTool, installTool
from defcon import Point
class ConstrainAngleEditingTool(EditingTool):
def getToolbarTip(self):
return "Constrain Angle"
def modifyDeltaForAngle(self, delta, angle):
'''Constrain delta to a given angle.'''
_tan1 = tan(radians(angle + 90))
_tan2 = tan(radians(angle))
if abs(_tan1) < abs(_tan2):
delta.x = -_tan1 * delta.y
else:
delta.y = _tan2 * delta.x
def modifyDraggingPoint(self, point, delta):
'''Constrain on-curve points to italic angle.'''
# get italic angle from font!
f = CurrentFont()
self.angle = f.info.italicAngle - 90
# calculate delta for current mouse down point
if self.mouseDownPoints:
fx, fy = self.mouseDownPoints[-1]
else:
fx, fy = point
delta.x = point.x - fx
delta.y = point.y - fy
# constrain delta to angle
if self.shiftDown:
self.modifyDeltaForAngle(delta, self.angle)
return point, delta
def _mouseDragged(self, point, delta):
'''Constrain off-curve points to italic angle.'''
# apply default _mouseDragged behavior first
shiftdown = self.shiftDown
self.shiftDown = False
super()._mouseDragged(point, delta)
self.shiftDown = shiftdown
# handle single off-curve point selection
if self.shiftDown and self.selection.containsSingleOffCurve():
# get selected off-curve point
offcurve = self.selection.selectedPoints[0]
# get related on-curve point
info = self.selection.selectionDataForPoint(offcurve)
anchor = info["anchor"]
# calculate delta for off-curve point
offcurveDelta = Point((offcurve.x - anchor.x, offcurve.y - anchor.y))
# constrain delta to angle
self.modifyDeltaForAngle(offcurveDelta, self.angle)
# update position of off-curve point
offcurve.x = anchor.x + offcurveDelta.x
offcurve.y = anchor.y + offcurveDelta.y
installTool(ConstrainAngleEditingTool())