There is an old Slavic calligraphy tradition, called ‘Russian monospaced Vyaz’ or just ‘Vyaz’. It’s unique in terms of special forms and rules of ligature generation. For example, take a look at works of a contemporary artist Viktor Pushkarev.

Once, a colleague of mine, Anna Shishlyakova drew a nice piece of Vyaz and since then I kept thinking if one can automatically generate such ligatures. Several years have passed and I finally found a weekend to make something like this:

the original drawing by Anna on the left side, the generated vyaz on the right side

General description

The current implementation consists of several components:

  • a configuration file that determines the size of symbols, kerning and ligature assembly parameters (as an example, I give a pack of several different configuration files with crafted parameters);
  • a font geometry file now contains Latin and Cyrillic symbols, plus Arabic numerals, it can be expanded;
  • a script that implements several rendering algorithms.

The current version renders the result in ASCII/unicode graphics, however, the whole core is implemented in a vector logic, so it is possible to rewrite a renderer to produce something like svg or high-resolution bitmap.

Core logic

a font grid scheme

In case you want to add new symbols and/or change how the font looks, you should understand several principles:

  1. Each symbol consists of a set of anchors and some edges between them.
  • The position of each anchor is given in terms of a simple grid:
  • for a horizontal offset I used the zero-based index of “vertical”, for example, ‘I’ has only one vertical, ‘U’ has two verticals, and ‘W’ has three vertical lines (note, ‘Z’ still has only two verticals),
  • for a vertical position I used this scale of 5 positions: b[ottom] < d[own] < m[iddle] < u[p] < t[op].

2. An edge is defined by three parameters:

  • the first anchor,
  • the second anchor,
  • the constraint on a slope of the edge:
  • ‘=’ means both anchors should be strictly on the same vertical position,
  • ‘<’ means the first anchor should be lower than the second, etc.

3. While merging two symbols into ligature the script checks if a left-most vertical of the right symbol conflicts wit a right-most vertical of the left symbol. If so, it tries to distort them somehow to avoid any conflicts. There are two types of distortion implemented:

  • if it’s possible to resize the only one vertical of symbol to remove conflicts without violation of edges constraints, it’s done.
  • Overwise, the whole symbol could be resized to avoid the collision, but it’s bad to resize too much,
  • If nothing helps, the script just puts these two symbols side-by-side separately.
different strategies of ligature construction

Few more words

You can grab a working code just in my github repo.

Despite the output of the asciivyaz script usually looks okay, consider to use it in conjunction with some other tools:

  • try to use lolcat to colorize the output just in a terminal,
  • try to use some online snippet renderers, like carbon to make snippets look better.

Some pictures



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store