from math import floor from defcon import Glyph, registerRepresentationFactory from mojo.events import postEvent from mojo.roboFont import OpenWindow from mojo.subscriber import ( Subscriber, WindowController, registerGlyphEditorSubscriber, registerSubscriberEvent, unregisterGlyphEditorSubscriber, ) from vanilla import FloatingWindow, PopUpButton, TextBox from merz import MerzPen def gridFactory(glyph, cellSize=100): pen = MerzPen() glyph = glyph.asFontParts() xMin, yMin, xMax, yMax = glyph.bounds for y in range(int(yMin), int(floor(yMax)), cellSize): for x in range(int(xMin), int(floor(xMax)), cellSize): if glyph.pointInside((x + cellSize / 2, y + cellSize / 2)): pen.rect((x, y, cellSize, cellSize)) return pen class GridSubscriber(Subscriber): debug = True controller = None glyphEditorDidSetGlyphDelay = 0 glyphEditorGlyphDidChangeOutlineDelay = 0 def build(self): self.glyphEditor = self.getGlyphEditor() self.container = self.glyphEditor.extensionContainer( identifier="com.roboFont.gridSubscriber", location="background", clear=True, ) self.gridLayer = self.container.appendBaseSublayer() def started(self): self.drawCells() def destroy(self): self.container.clearSublayers() def glyphEditorDidSetGlyph(self, info): self.drawCells() def glyphEditorGlyphDidChangeOutline(self, info): self.drawCells() def controllerDidChange(self, info): self.drawCells() def drawCells(self): if self.controller is None: return self.gridLayer.clearSublayers() cellSize = int(self.controller.w.popUpButton.getItem()) glyph = self.glyphEditor.getGlyph() merzPen = glyph.getRepresentation("gridRepresentation", cellSize=cellSize) self.gridLayer.appendPathSublayer( fillColor=(0, 0, 0, 0.5), path=merzPen.path ) class GridController(WindowController): debug = True def build(self): self.w = FloatingWindow((120, 50), "Grid") self.w.caption = TextBox((10, 14, 40, 30), "Size:") self.w.popUpButton = PopUpButton( (50, 10, -10, 30), items=["25", "50", "100"], callback=self.popUpButtonCallback, ) def started(self): GridSubscriber.controller = self registerGlyphEditorSubscriber(GridSubscriber) def destroy(self): GridSubscriber.controller = None unregisterGlyphEditorSubscriber(GridSubscriber) def popUpButtonCallback(self, sender): postEvent("controllerDidChange") if __name__ == "__main__": registerRepresentationFactory(Glyph, "gridRepresentation", gridFactory) registerSubscriberEvent( subscriberEventName="controllerDidChange", methodName="controllerDidChange", lowLevelEventNames=["controllerDidChange"], dispatcher="roboFont", delay=0, debug=True, ) OpenWindow(GridController)