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.
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; } |
You should have made a font for extra Spanish.
[…] One of the examples for class was a randomized column grid, wherein the column widths generate differently every time. For my own program, I chose to randomize both the width and height of the columns. I used these values as size parameters for letters of the font that I designed for the previous assignment. […]