Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / game

Procedural Gyph Language

4.00/5 (1 vote)
19 Oct 2012CPOL2 min read 15K   88  
A New UI Language
 


Image 1




Image 2

Introduction

I thought it would be kinda cool to teach the computer to auto generate glyphs that uniquely represent words, but do so procedurally like some sci-fi alien language. Kanji and other glyph/stroke based symbols evolved over time and there isn't a programmatic pattern to generate the symbols from an alphabet. Because I've always been interested in things that improve efficiency such as short hand, I figured it might be interesting to procedurally generate glyphs/Kanji like symbols from text.

Background

Well, this is what happens when I watch too much Dr. Who.

Languages are cool, so I created a sort of "procedural" generation of glyphs like "kanji" for Japanese, but it's just an alphabet translation.  

Using the Code

First text is split into words, then the letters are "found" in a map, then the map locations are turned into a cursive like stroke connecting 2-3 points at a time to generate a glyph. There are a few cool tricks in the code. First I created a 2D map of the text (array of strings, each string is a row). When a character is found, it's location is the row/column in the map. This is then translated into a graphic location, and appended to the list. This list is then broken into pieces in a way to generally make 2-4 locations into a stroke, like a curved stroke of a brush. This also checks for double letters (adding additional markings) and makes sure that if there were say, 10 location it doesn't get broken into 2 strokes of 4 points and a two point in the end, but into a 4 pnt, and two 3 pnt strokes. 

The code is also a decent example of double buffering and of drawing curves.

Map

The points are selected from the map:

string[] map = {
               "1234567890",
               "QWERTYUIOP",
               "qwertyuiop",
               "`~!@#$%^&**()-_=+",
               "ASDFGHJKL",
               "asdfghjkl",
               ",<.>/?;:'\"[{]}\\|",
               "ZXCVBNM",
               "zxcvbnm",
               };
pnts.Add(new PointF(xInd, yInd));
for (int j = 0; j < words[i].Length; j++)
{
    float x = 0;
    float y = 0;
    char c = words[i][j];
    for (int k = 0; k < map.Length; k++)
    {
        int m = map[k].IndexOf(c);
        if (m >= 0)
        {
            // location is kth row, mth thing.
            // Dividing vertically by map rows, we have the y value.
            y = k * wordHeightScale;
            x = m * wordWidthScale;
            break;
        }
    }
    pnts.Add(new PointF(x + xInd, y + yInd));
}
if (pnts.Count > 1)
{
    renderLine(g, pnts, wordWidthScale, wordHeightScale);
}

Line Rendering

Rendering the line means breaking first into strokes, drawing a stroke then dealing with duplicate letters.

formSegments(pntsArray, segs);
using (Pen p = new Pen(Color.Black, 1.5f))
{
    // This is just for artistic stuff.
    for (int i = 0; i < segs.Count; i++)
    {
        renderStroke(g, p, segs[i]);
    }
... Duplicate letter code.

Segments are made:

protected void formSegments(PointF[] pnts, List<PointF[]> segs)
{
    // The goal is no stroke is less than 3 points, and ideally all are 4 point.
    // if needed do the last (or only) as a 5 point stroke.
    int start = 0;
    while ((start < pnts.Length) && (segs.Count < 20))
    {
        int rem = pnts.Length - start;
        if (rem > 6)
        {
            // If greater than 6, take a 4 stroke bite.
            PointF[] p = new PointF[4];
            for (int i = 0; i < 4; i++) p[i] = pnts[start + i];
            start += 4;
            rem -= 4;
            segs.Add(p);
        }
        if (rem > 5)
        {
            // Remainder is 6 or more, so taking a stroke of three is good.
            PointF[] p = new PointF[3];
            for (int i = 0; i < 3; i++) p[i] = pnts[start + i];
            start += 3;
            rem -= 3;
            segs.Add(p);
        }
        if (rem <= 5)
        {
            PointF[] p = new PointF[rem];
            for (int i = 0; i < rem; i++) p[i] = pnts[start + i];
            start += rem;
            segs.Add(p);
        }
    }
}

Then the lines get drawn:

C#
protected void renderStroke(Graphics g, Pen p, PointF[] pntsArray)
{
    g.DrawCurve(p, pntsArray, 0.75f);

    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < pntsArray.Length; j++)
        {
            pntsArray[j].X += i * 0.1f;
            pntsArray[j].Y += i * 0.2f;
        }
        g.DrawCurve(p, pntsArray, 0.75f);
    }
}

Use in Applications

The glyphs are interesting for decoration, or to create different UI experiences.

One way to think of this submission is as art, or another as looking at different ways a computer could communicate with another computer in a more graceful way than just binary or bar codes. Another thing that might be neat is to use phonetics, and mix in color.

In any case, it's for fun and I hope someone has fun with it. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)