Last active
October 11, 2021 18:24
-
-
Save gferreira/fd2581497b86e7b29a51e9110ad87abc to your computer and use it in GitHub Desktop.
a simple move glyph tool for RF4 -- built with Subscriber and Merz
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from vanilla import FloatingWindow, CheckBox, Button, TextBox | |
from mojo.UI import NumberEditText, UpdateCurrentGlyphView | |
from mojo.roboFont import CurrentGlyph | |
from mojo.subscriber import Subscriber, WindowController, registerGlyphEditorSubscriber | |
from mojo.pens import DecomposePointPen | |
class MoveGlyphsPanel(Subscriber, WindowController): | |
# ---------- | |
# attributes | |
# ---------- | |
title = "move" | |
key = 'com.example.myToolkit.move' | |
defaults = { | |
'deltaX' : 70, | |
'deltaY' : 20, | |
} | |
width = 123 | |
padding = 10 | |
textHeight = 20 | |
sizeStyle = 'small' | |
backgroundFillColor = 1, 0, 0, 0.25 | |
backgroundStrokeColor = 1, 0, 0, 1 | |
backgroundStrokeWidth = 2 | |
# ------------------ | |
# Subscriber methods | |
# ------------------ | |
def build(self): | |
# build window | |
self.height = self.textHeight * 4 + self.padding * 5 | |
self.w = FloatingWindow((self.width, self.height), self.title) | |
x = y = p = self.padding | |
col = (self.width - p*2) / 2 | |
self.w.labelX = TextBox( | |
(x, y, col, self.textHeight), | |
'x delta', | |
sizeStyle=self.sizeStyle) | |
self.w.deltaX = NumberEditText( | |
(x + col, y, -p, self.textHeight), | |
text=self.defaults['deltaX'], | |
callback=self.updatePreviewCallback, | |
sizeStyle=self.sizeStyle, | |
allowFloat=False, | |
continuous=False) | |
y += self.textHeight + p | |
self.w.labelY = TextBox( | |
(x, y, col, self.textHeight), | |
'y delta', | |
sizeStyle=self.sizeStyle) | |
self.w.deltaY = NumberEditText( | |
(x + col, y, -p, self.textHeight), | |
text=self.defaults['deltaY'], | |
callback=self.updatePreviewCallback, | |
sizeStyle=self.sizeStyle, | |
allowFloat=False, | |
continuous=False) | |
y += self.textHeight + p | |
self.w.applyButton = Button( | |
(x, y, -p, self.textHeight), | |
'apply', | |
sizeStyle=self.sizeStyle, | |
callback=self.applyCallback) | |
y += self.textHeight + p | |
self.w.preview = CheckBox( | |
(x, y, -p, self.textHeight), | |
"preview", | |
value=True, | |
callback=self.updatePreviewCallback, | |
sizeStyle=self.sizeStyle) | |
# setup Merz layers | |
glyphEditor = self.getGlyphEditor() | |
self.backgroundContainer = glyphEditor.extensionContainer( | |
identifier=f'{self.key}.background', | |
location="background", | |
clear=True) | |
self.backgroundLayer = self.backgroundContainer.appendPathSublayer( | |
fillColor=self.backgroundFillColor, | |
strokeColor=self.backgroundStrokeColor, | |
strokeWidth=self.backgroundStrokeWidth, | |
name="backgroundLayer") | |
self.previewContainer = glyphEditor.extensionContainer( | |
identifier=f'{self.key}.preview', | |
location="preview", | |
clear=True) | |
self.previewLayer = self.previewContainer.appendPathSublayer( | |
fillColor=(0,0,0,1), | |
strokeColor=None, | |
name="previewLayer") | |
def started(self): | |
self.w.open() | |
def destroy(self): | |
self.backgroundContainer.clearSublayers() | |
self.previewContainer.clearSublayers() | |
# --------- | |
# observers | |
# --------- | |
def glyphEditorDidSetGlyph(self, info): | |
glyph = info["glyph"] | |
self._drawLayers(glyph) | |
def glyphEditorGlyphDidChange(self, info): | |
glyph = info["glyph"] | |
self._drawLayers(glyph) | |
# --------- | |
# callbacks | |
# --------- | |
def updatePreviewCallback(self, sender): | |
self._drawLayers(CurrentGlyph()) | |
def applyCallback(self, sender): | |
glyph = CurrentGlyph() | |
if glyph is None: | |
return | |
glyph.prepareUndo('move glyphs') | |
self._makeGlyph(glyph) | |
glyph.changed() | |
glyph.performUndo() | |
# ------- | |
# methods | |
# ------- | |
def _drawLayers(self, glyph): | |
# nothing to draw | |
if glyph is None or not glyph.bounds or not self.w.preview.get(): | |
self.backgroundLayer.setVisible(False) | |
self.previewLayer.setVisible(False) | |
return | |
# draw background & preview layers | |
self.backgroundLayer.setVisible(True) | |
self.previewLayer.setVisible(True) | |
resultGlyph = self._makeGlyph(glyph, preview=True) | |
resultPath = resultGlyph.getRepresentation("merz.CGPath") | |
self.backgroundLayer.setPath(resultPath) | |
self.previewLayer.setPath(resultPath) | |
def _makeGlyph(self, glyph, preview=False): | |
if preview: | |
dstGlyph = RGlyph() | |
dstGlyph.width = glyph.width | |
dstPen = dstGlyph.getPointPen() | |
decomposePen = DecomposePointPen(glyph.font, dstPen) | |
glyph.drawPoints(decomposePen) | |
glyph = dstGlyph | |
dx = self.w.deltaX.get() | |
dy = self.w.deltaY.get() | |
glyph.moveBy((dx, dy)) | |
return glyph | |
if __name__ == "__main__": | |
registerGlyphEditorSubscriber(MoveGlyphsPanel) | |
# OpenWindow(MoveGlyphsPanel) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment