This example shows a simple stencil preview tool. The result is produced by subtracting the background layer from the foreground.

from vanilla import FloatingWindow
from defconAppKit.windows.baseWindow import BaseWindowController
from mojo.glyphPreview import GlyphPreview
from mojo.events import addObserver, removeObserver
from mojo.roboFont import CurrentGlyph

class StencilPreview(BaseWindowController):

    def __init__(self):
        self.glyph = CurrentGlyph()
        # create a window
        self.w = FloatingWindow((400, 400), "Stencil Preview", minSize=(200, 200))
        # add a glyph preview to the window
        self.w.preview = GlyphPreview((0, 0, -0, -0))
        # add an observer to receive callbacks when a glyph changes in the glyph view
        addObserver(self, "viewDidChangeGlyph", "viewDidChangeGlyph")
        # open the window
        self.updateGlyph()
        self.w.open()

    def viewDidChangeGlyph(self, notification):
        # notification when the glyph changes in the glyph view
        glyph = CurrentGlyph()
        self.unsubscribeGlyph()
        self.subscribeGlyph(glyph)
        self.updateGlyph()

    def glyphChanged(self, notification):
        self.updateGlyph()

    def updateGlyph(self):
        glyph = self.glyph
        # if there is no glyph, just set `None` in the preview
        if glyph is None:
            self.w.preview.setGlyph(None)
            return
        # get the foreground and background layers
        foreground = glyph.getLayer("foreground")
        background = glyph.getLayer("background")
        # get the result by subtracting background from foreground layer
        result = foreground % background
        # set the result in the preview view
        self.w.preview.setGlyph(result)

    def subscribeGlyph(self, glyph):
        # subscribe to glyph
        self.glyph = glyph
        # add an observer to glyph data changes
        self.glyph.addObserver(self, "glyphChanged", "Glyph.Changed")

    def unsubscribeGlyph(self):
        # unsubscribe from glyph
        if self.glyph is None:
            return
        # remove observer from the glyph
        self.glyph.removeObserver(self, "Glyph.Changed")

    def windowCloseCallback(self, sender):
        # notification when the floating window is closed
        # remove observer for the current glyph
        removeObserver(self, "viewDidChangeGlyph")
        # unsubscribe the glyph
        self.unsubscribeGlyph()
        super(StencilPreview, self).windowCloseCallback(sender)

# open the floating window
OpenWindow(StencilPreview)
Last edited on 10/08/2019