This example shows how to register a defcon.Glyph representation that outputs a merzPen storing a glyph bitmap. The pixel size is controlled through a vanilla.Window.

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)

Last edited on 01/09/2021