from defcon import Glyph, registerRepresentationFactory import drawBot as db 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 def blurredGlyphFactory(glyph, radius=1): glyph = glyph.asFontParts() bounds = glyph.bounds if not bounds: return (0, 0), (0, 0), None xMin, yMin, xMax, yMax = glyph.bounds width = xMax - xMin height = yMax - yMin db.newDrawing() db.newPage(width, height) db.translate(-xMin, -yMin) bezierPath = db.BezierPath(glyphSet=glyph.layer) glyph.draw(bezierPath) imObj = db.ImageObject() with imObj: db.size(width+radius*2, height+radius*2) db.drawPath(bezierPath) imObj.gaussianBlur(radius=radius) x, y = imObj.offset() db.image(imObj, (x, y)) nsImage = db.saveImage("NSImage") db.endDrawing() return (xMin, yMin), (width, height), nsImage class BlurredSubscriber(Subscriber): debug = True controller = None glyphEditorDidSetGlyphDelay = 0 glyphEditorGlyphDidChangeOutlineDelay = 0 def build(self): self.glyphEditor = self.getGlyphEditor() self.container = self.glyphEditor.extensionContainer( identifier="com.roboFont.blurredSubscriber", location="background", clear=True, ) self.imageLayer = self.container.appendImageSublayer() 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.imageLayer.clearSublayers() radius = int(self.controller.w.popUpButton.getItem()) glyph = self.glyphEditor.getGlyph() origin, size, nsImage = glyph.getRepresentation("blurredRepresentation", radius=radius) if nsImage: self.imageLayer.setSize(size) self.imageLayer.setPosition(origin) self.imageLayer.setImage(nsImage) class BlurredController(WindowController): debug = True def build(self): print("BlurredController") self.w = FloatingWindow((120, 50), "Blurred Glyph") self.w.caption = TextBox((10, 14, 50, 30), "Radius:") self.w.popUpButton = PopUpButton( (65, 10, -10, 30), items=["5", "10", "15"], callback=self.popUpButtonCallback, ) self.w.open() def started(self): BlurredSubscriber.controller = self registerGlyphEditorSubscriber(BlurredSubscriber) def destroy(self): BlurredSubscriber.controller = None unregisterGlyphEditorSubscriber(BlurredSubscriber) def popUpButtonCallback(self, sender): postEvent("controllerDidChange") if __name__ == "__main__": registerRepresentationFactory(Glyph, "blurredRepresentation", blurredGlyphFactory) registerSubscriberEvent( subscriberEventName="controllerDidChange", methodName="controllerDidChange", lowLevelEventNames=["controllerDidChange"], dispatcher="roboFont", delay=0, debug=True, ) OpenWindow(BlurredController)