A Font of My Very Own

My first foray into font design was a wondrous accident. Our assignment was to design a font for a word, and Rune suggested that we use the Geomerative library for Processing, which converts true-type fonts into a series of points that can be altered. I had a lot of difficulty getting the library to work; after hours of dealing with errors, I gave up and started again without it. With only a few hours to go before my printing session at AMS, I devised a formula for an alphabet.

I figured it would be easiest to space out the letters if they all had the same dimensions. I started with a filled rectangle on the left side, and fit the other parts of the letter into an imaginary rectangle on the right side. This worked perfectly for the word I had chosen for the project, “muffin.” Even though this was enough to finish the project with, I was really excited and sketched out plans for the rest of the alphabet. My rules had to change a little to accomodate the different letter shapes. Some letters had to be lower case to distinguish them from similar letters.
font notes

The Letter class contains all of the instructions for building the letters of the font. When a letter object is called, it requires two position values (xpos, ypos) and two size parameters (distX, distY). The parameter distX represents half of the letter’s width, and the parameter distY represents the letter’s height. This structure makes the font completely scalable. It changes shape and size when the distX and distY values change, as these two examples illustrate:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
class Letter
{
  float distX, distY;
  float xpos, ypos;
 
  Letter(float xpos_, float ypos_, float distX_, float distY_){
    distX = distX_;  //left half of letter
    distY = distY_;  //right half of letter
    xpos = xpos_;  //xpos of top left corner of letter
    ypos = ypos_;  //ypos of top left corner of letter
  }
 
  void a()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos, xpos + 2*distX, ypos);  //top horiz line
    canvas.line(xpos + distX, ypos + distY/2, xpos + 2*distX, ypos + distY/2);  //middle horiz line
    canvas.line(xpos + 2*distX, ypos, xpos + 2*distX, ypos + distY);  //right vert line
  }
 
  void b()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos + distY/2, xpos + 2*distX, ypos + distY/2);  //middle horiz line
    canvas.line(xpos + 2*distX, ypos + distY/2, xpos + 2*distX, ypos + distY);  //1/2 right vert line
    canvas.line(xpos, ypos + distY, xpos + 2*distX, ypos + distY);  //bottom horiz line
  }
 
  void c()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos, xpos + 2*distX, ypos);  //top horiz line
    canvas.line(xpos + distX, ypos + distY, xpos + 2*distX, ypos + distY);  //bottom horiz line  
  }
 
  void d()
  {
    canvas.rect(xpos + distX, ypos, distX, distY);  //filled right side box
    canvas.line(xpos, ypos + distY/2, xpos + distX, ypos + distY/2);  //middle horiz line left
    canvas.line(xpos, ypos + distY/2, xpos, ypos + distY);  //1/2 left vert line bottom
    canvas.line(xpos, ypos + distY, xpos + distX, ypos + distY);  //bottom horiz line left
  }
 
  void e()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos, xpos + 2*distX, ypos);  //top horiz line
    canvas.line(xpos + distX, ypos + distY/2, xpos + 2*distX, ypos + distY/2);  //middle horiz line
    canvas.line(xpos + distX, ypos + distY, xpos + 2*distX, ypos + distY);  //bottom horiz line
  }
 
  void f()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos, xpos + 2*distX, ypos);  //top horiz line
    canvas.line(xpos + distX, ypos + distY/3, xpos + 2*distX, ypos + distY/3);  //1/3 horiz line
  }
 
  void g()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos, xpos + 2*distX, ypos);  //top horiz line
    canvas.line(xpos + distX, ypos + distY, xpos + 2*distX, ypos + distY);  //bottom horiz line
    canvas.line(xpos + 2*distX, ypos + distY/2, xpos + 2*distX, ypos + distY);  //1/2 right vert line  
  }
 
  void h()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos + distY/2, xpos + 2*distX, ypos + distY/2);  //middle horiz line
    canvas.line(xpos + 2*distX, ypos, xpos + 2*distX, ypos + distY);  //right vert line
  }
 
  void i()  //special case: doesn't have right side lines
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
  }
 
  void j()
  {
    canvas.rect(xpos + distX, ypos, distX, distY);  //filled right side box
    canvas.line(xpos, ypos + 2*distY/3, xpos, ypos + distY);  //2/3 left vert line bottom
    canvas.line(xpos, ypos + distY, xpos + distX, ypos + distY);  //bottom horiz line left
  }
 
  void k()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos + distY/2, xpos + 2*distX, ypos);  //mid to top right diagonal
    canvas.line(xpos + distX, ypos + distY/2, xpos + 2*distX, ypos + distY);  //mid to bottom right diagonal
  }
 
  void l()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos + distY, xpos + 2*distX, ypos + distY);  //bottom horiz line  
  }
 
  void m()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos, xpos + 2*distX, ypos);  //top horiz line
    canvas.line(xpos + 3*distX/2, ypos, xpos + 3*distX/2, ypos + distY/2);  //mid-top vert line
    canvas.line(xpos + 2*distX, ypos, xpos + 2*distX, ypos + distY);  //right vert line
  }
 
  void n()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos, xpos + 2*distX, ypos);  //top horiz line
    canvas.line(xpos + 2*distX, ypos, xpos + 2*distX, ypos + distY);  //right vert line
  }
 
  void o()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos, xpos + 2*distX, ypos);  //top horiz line
    canvas.line(xpos + 2*distX, ypos, xpos + 2*distX, ypos + distY);  //right vert line
    canvas.line(xpos + distX, ypos + distY, xpos + 2*distX, ypos + distY);  //bottom horiz line }
  }
 
  void p()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos, xpos + 2*distX, ypos);  //top horiz line
    canvas.line(xpos + distX, ypos + distY/2, xpos + 2*distX, ypos + distY/2);  //middle horiz line
    canvas.line(xpos + 2*distX, ypos, xpos + 2*distX, ypos + distY/2);  //1/2 right vert line
  }
 
  void q()
  {
    canvas.rect(xpos + distX, ypos, distX, distY);  //filled right side box
    canvas.line(xpos, ypos, xpos + 2*distX, ypos);  //top horiz line left
    canvas.line(xpos, ypos + distY/2, xpos + distX, ypos + distY/2);  //middle horiz line left
    canvas.line(xpos, ypos, xpos, ypos + distY/2);  //1/2 left vert line
  }
 
  void r()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos, xpos + 2*distX, ypos);  //top horiz line
    canvas.line(xpos + distX, ypos + distY/2, xpos + 2*distX, ypos + distY/2);  //middle horiz line
    canvas.line(xpos + 2*distX, ypos, xpos + 2*distX, ypos + distY/2);  //1/2 right vert line
    canvas.line(xpos + distX, ypos + distY/2, xpos + 2*distX, ypos + distY);  //mid to bottom right diagonal
  }
 
  void s()
  {
    canvas.rect(xpos, ypos, distX, distY/2);  //filled top left 1/2 box
    canvas.line(xpos + distX, ypos, xpos + 2*distX, ypos);  //top horiz line
    canvas.rect(xpos + distX, ypos + distY/2, distX, distY/2);  //filled bottom right 1/2 box
    canvas.line(xpos, ypos + distY, xpos + distX, ypos + distY);  //bottom horiz line
  }
 
  void t()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos + distY/2, xpos + 2*distX, ypos + distY/2);  //middle horiz line
    canvas.line(xpos + distX, ypos + distY, xpos + 2*distX, ypos + distY);  //bottom horiz line
  }
 
  void u()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos + distY, xpos + 2*distX, ypos + distY);  //bottom horiz line
    canvas.line(xpos + 2*distX, ypos, xpos + 2*distX, ypos + distY);  //right vert line
  }
 
  void v()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos + distY, xpos + 2*distX, ypos);  //right vert line
  }
 
  void w()
  {
    canvas.rect(xpos, ypos, distX, distY);  //filled left side box
    canvas.line(xpos + distX, ypos + distY, xpos + 2*distX, ypos + distY);  //bottom horiz line
    canvas.line(xpos + 2*distX, ypos, xpos + 2*distX, ypos + distY);  //right vert line
    canvas.line(xpos + 3*distX/2, ypos + distY, xpos + 3*distX/2, ypos + distY/2);  //mid-bottom vert line
  }
 
  void y()
  {
    canvas.rect(xpos + distX, ypos, distX, distY);  //filled right side box
    canvas.line(xpos, ypos + distY/2, xpos + distX, ypos + distY/2);  //middle horiz line left
    canvas.line(xpos, ypos, xpos, ypos + distY/2);  //1/2 left vert line
    canvas.line(xpos, ypos + distY, xpos + distX, ypos + distY);  //bottom horiz line left
  }
 
  void z()
  {
    canvas.rect(xpos, ypos + distY/2, distX, distY/2);  //filled bottom left 1/2 box
    canvas.line(xpos, ypos, xpos + distX, ypos);  //top left horiz line
    canvas.rect(xpos + distX, ypos, distX, distY/2);  //filled top right 1/2 box
    canvas.line(xpos + distX, ypos + distY, xpos + 2*distX, ypos + distY);  //bottom right horiz line
  }
}

This is the code for the main sketch:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//Kim Ash
//Printing Code
//wordFont - typeface based on rule system
 
PGraphics canvas;
int canvas_width = 5100;
int canvas_height = 2550;
 
float ratioWidth = 1;
float ratioHeight = 1;
float ratio = 1;
 
Letter m;
Letter u;
Letter f1;
Letter f2;
Letter i;
Letter n;
 
float distX = canvas_width/20;
float distY = 8*distX;
 
void setup()
{ 
  size(510, 255);
  canvas = createGraphics(canvas_width, canvas_height);
  calculateResizeRatio();
 
  canvas.beginDraw();
    canvas.colorMode(HSB, 360, 100, 100);
    canvas.background(360);
    canvas.smooth();
    canvas.fill(32, 86, 99);
    canvas.stroke(32, 86, 99);
    canvas.strokeWeight(canvas.height/30);
 
    canvas.pushMatrix();
    canvas.translate(canvas.width/10, canvas.height/9);
    m = new Letter(0, 0, distX, distY);
    u = new Letter(0 + 3*distX, 0, distX, distY);
    f1 = new Letter(0 + 6*distX, 0, distX, distY);
    f2 = new Letter(0 + 9*distX, 0, distX, distY);
    i = new Letter(0 + 12*distX, 0, distX, distY);
    n = new Letter(0 + 14*distX, 0, distX, distY);
 
    m.m();
    u.u();
    f1.f();
    f2.f();
    i.i();
    n.n();
    canvas.popMatrix();
 
  canvas.endDraw();
 
  float resizedWidth = (float) canvas.width * ratio;
  float resizedHeight = (float) canvas.height * ratio;
  //displays canvas onscreen
  image(canvas, (width/2) - (resizedWidth/2), (height/2) - (resizedHeight/2), resizedWidth, resizedHeight);
 
  canvas.save("font.tiff");
}
 
 
/* resizing function */
void calculateResizeRatio()
{
  ratioWidth = (float) width / (float) canvas.width;
  ratioHeight = (float) height / (float) canvas.height;
 
  if(ratioWidth < ratioHeight)  ratio = ratioWidth;
  else                          ratio = ratioHeight;
}