This example shows how to register a defcon.Kerning representation that outputs the flat kerning of a font. Considered that kerning depends on defcon.Groups too, the script registers a subscriber to make sure the representation cache is invalidated if a kerning group is edited.

from time import time

from defcon import Kerning, registerRepresentationFactory
from mojo.subscriber import Subscriber, registerCurrentFontSubscriber

FIRST_PREFIX = "public.kern1."
SECOND_PREFIX = "public.kern2."


class KerningGroupsWatcher(Subscriber):

    debug = True

    fontGroupsDidChangeDelay = 0
    def fontGroupsDidChange(self, info):
        info["font"].kerning.changed()
        print("an edit to groups invalidates the kerning cache!")


def flatKerningFactory(kerning):
    print("compute flat kerning!")
    flatK = {}
    font = kerning.font

    for pair, correction in kerning.items():
        first, second = pair

        # both groups
        if first.startswith(FIRST_PREFIX) and second.startswith(SECOND_PREFIX):
            for firstGlyph in font.groups[first]:
                for secondGlyph in font.groups[second]:
                    flatK[(firstGlyph, secondGlyph)] = correction

        # first group, second glyph
        elif first.startswith(FIRST_PREFIX):
            for firstGlyph in font.groups[first]:
                flatK[(firstGlyph, second)] = correction

        # first glyph, second group
        elif second.startswith(SECOND_PREFIX):
            for secondGlyph in font.groups[second]:
                flatK[(first, secondGlyph)] = correction

        # first glyph, second glyph
        else:
            flatK[(first, second)] = correction

    return flatK


if __name__ == "__main__":
    registerCurrentFontSubscriber(KerningGroupsWatcher)
    registerRepresentationFactory(Kerning, "flatKerningRepresentation", flatKerningFactory)

    font = CurrentFont()

    # first computation
    start = time()
    flatKerning = font.kerning.getRepresentation("flatKerningRepresentation")
    end = time()
    print(end - start)
    print(len(flatKerning))

    # retrieve the cache
    start = time()
    end = time()
    print(end - start)
    print(len(flatKerning))

    # edit the groups
    font.groups[f"{FIRST_PREFIX}.someGroup"] = ["A", "B", "C"]

    # compute again
    start = time()
    flatKerning = font.kerning.getRepresentation("flatKerningRepresentation")
    end = time()
    print(end - start)
    print(len(flatKerning))

    # remove the pseudo group
    del font.groups[f"{FIRST_PREFIX}.someGroup"]

Last edited on 01/09/2021