Tutorial 12: Working with Fonts

Text

The most basic unit for storing text in a Processing program is the char (short for character) data type. We will see uses for the char data type in future tutorials when we look at interaction with the keyboard. The most common data type for storing text that we want to manipulate or display is the String data type. Strings store sequences of characters, much like a sentence, for example:

    String str = "This is a string.";

    A String can be appended to another String using the + operator, like this:

      String str1 = "Roses are red.";
      String str2 = "Violets are blue."
      String str3 = str1 + str2;
      println(str3);

      If you run this code you'll notice that it will print Roses are red.Violets are blue. to the console. Notice that no character is inserted between the sentences. We can retify this by appended a character between the strings.

        String str1 = "Roses are red.";
        String str2 = "Violets are blue."
        String str3 = str1 + " " + str2;
        println(str3);

        This will print Roses are red. Violets are blue. to the console. Composing and printing text to the console like this can be very helpful when trying to understand the behaviour of our programs, e.g., when we want to debug our code.

        Displaying text

        To draw text to the display window, we use the text() function, which works in two different ways. If we specify just an (x, y) coordinate to draw the string at, then the text will be drawn in a single line relative to the given coordinate:

        • Show Sketch
        /** @peep sketchcode */
        size(100, 100);
        background(204);
        fill(0);
        text("LAX", 40, 30);
        text("AMS", 40, 60);
        text("FRA", 40, 90);

        Alternatively, we can specify a rectangular area of the screen to draw the text inside. In this case, Processing will wrap the text to fit as much of the text inside the rectangle as possible:

        • Show Sketch
        /** @peep sketchcode */
        size(100, 100);
        background(204);
        fill(0); 
        String s = "Response is the medium"; 
        text(s, 10, 20, 80, 50);

        Write a sketch that draws a piece of text within a rectangle that it too small to hold all of it. How does Processing handle this situation?

        Displaying Text in Different Colours

        We control the colour that text is drawn in using the fill() function, i.e., the text is drawn as a filled shape without an outline. The following two sketches show how we draw text in different colours and with different opacity by changing the call to fill():

        • Show Sketch
        /** @peep sketchcode */
        size(100, 100);
        background(204);
        fill(128, 0, 0);
        text("RED", 40, 30);
        fill(0, 128, 0);
        text("GRN", 40, 60);
        fill(0, 0, 128);
        text("BLU", 40, 90);
        • Show Sketch
        /** @peep sketchcode */
        size(100, 100);
        background(204);
        fill(0, 64);
        text("RED", 40, 30);
        text("GRN", 40, 60);
        text("BLU", 40, 90);

        Creating a Dropshadow

        We can overlay text on top of the same text drawn with an offset to create a simple dropshadow effect. In the following example the dropshadow is drawn with a light opacity so that it would work when overlaid on any colour background, or even over an image. Using a dropshadow in this way can significantly increase the visibility of small text when it must be drawn on complex backgrounds.

        • Show Sketch
        /** @peep sketchcode */
        size(100, 100);
        background(204);
        String s = "Response is the medium"; 
        fill(0, 64);
        text(s, 11, 21, 80, 50);
        fill(255);
        text(s, 10, 20, 80, 50);

        Practice drawing text by creating a sketch that overlays multiple strings to form a pattern. Use opacity to create complex regions. Note: you may want to use the textSize() function that we covered in the lecture to vary the size of the default font.

        Fonts

        Processing has a unique data type called PFont to store font data. PFont, like PImage, is a class, which is a way that we can package up data and methods that relate to that data together in a single place. The fonts installed on a system can be accessed using the PFont.list() method. On the desktop this will typically display a long list of fonts installed on a computer, but in the browser this will only provide access to a few standard fonts:

        • Show Sketch
        /** @peep sketchcode */
        size(300, 300);
        String[] fontList = PFont.list();
        background(0);
        fill(255);
        for (int i = 0; i < height/20; i++) {
          textFont(createFont(fontList[i], 18));
          text(fontList[i], 20, (i+1)*20);
        }

        Loading fonts

        To load fonts in Processing.js we need to use a special comment, as we did previously for images, that tells Processing.js that we need to use a specific font and that it should "preload" it for us. The way that we specify the font is slightly different from images because instead of using the preload keyword we use the font keyword, like this:

          /* @pjs font=/media/css/Chunkfive-webfont.ttf; */

          Having told Processing.js that we want to access a font, we then create the font in memory using the createFont() function, being careful to ensure that we use the same address to reference the font as we did in the comment, like this:

            PFont font = createFont("/media/css/Chunkfive-webfont.ttf", 32);

            This will store the PFont object in a variable that we can use to specify the font that we want to draw with. To specify that we want to make the font the one that we want to use we use the textFont() function:

              textFont(font);

              Putting this all together we can draw text in any font that we can load from a URL. This example uses the standard Chunkfive font that Peep uses for all headings:

              • Show Sketch
              /* @pjs font=/media/css/Chunkfive-webfont.ttf; */
              /** @peep sketchcode */
              size(100, 100);
              background(204);
              PFont font = createFont("/media/css/Chunkfive-webfont.ttf", 32);
              textFont(font);
              fill(0);
              text("LAX", 0, 40);
              text("AMS", 0, 70);
              text("FRA", 0, 100);

              You can use other fonts either by finding URLs that point to them on other web sites or by uploading them to Peep in your profile page. Here's an example using a font that I've uploaded to my profile:

              • Show Sketch
              /* @pjs font=/uploads/1/gooddog.otf; */
              /** @peep sketchcode */
              size(100, 100);
              background(204);
              PFont font = createFont("/uploads/1/gooddog.otf", 32);
              textFont(font);
              size(100, 100);
              background(204);
              fill(0); 
              String s = "Response is the medium"; 
              text(s, 10, 20, 80, 50);

              Practice using a font by uploading one to your profile and changing the above code to use it. The font must be in either TrueType (.ttf) or OpenType (.otf) format. Note: you can find good collections of free to use TrueType and OpenType fonts online at sites like Font Squirrel or the Google Web Font project.

              You are not limited to using a single font in a sketch. To use multiple fonts, simply load them into different variables at the start of your sketch and switch which font you use to display text with using the textFont() function:

              • Show Sketch
              /* @pjs font="/uploads/1/rabiohead.ttf","/uploads/1/gooddog.otf"; */
              /** @peep sketchcode */
              size(100, 100);
              background(204);
              PFont rabiohead = createFont("/uploads/1/rabiohead.ttf", 24);
              PFont gooddog = createFont("/uploads/1/gooddog.otf", 24);
              fill(0); 
              textFont(rabiohead); 
              text("Rabiohead", 6, 45); 
              textFont(gooddog); 
              text("GoodDog", 2, 80);

              Notice how the comment at the beginning of the sketch lists both fonts that it uses separated by a comma.

              Practice using multiple fonts in a sketch by uploading another font to your profile and changing the above sketch to use your fonts. Extend the sketch to produce a more complex pattern using your fonts.

              Changing the appearance of a font

              Just as with the text that we drew before, we can change the colour and size of a text drawn in a font by changing the fill colour and the size and alignment of the font. For example, we can change the colour and opacity just as before:

              • Show Sketch
              /* @pjs font=/media/css/Chunkfive-webfont.ttf; */
              /** @peep sketchcode */
              size(100, 100);
              background(204);
              PFont font = createFont("/media/css/Chunkfive-webfont.ttf", 32);
              textFont(font);
              fill(128, 0, 0); // Red 
              text("RED", 0, 40); 
              fill(0, 128, 0); // Green 
              text("GRN", 0, 70); 
              fill(0, 0, 128); // Blue 
              text("BLU", 0, 100);
              • Show Sketch
              /* @pjs font=/media/css/Chunkfive-webfont.ttf; */
              /** @peep sketchcode */
              size(100, 100);
              background(204);
              PFont font = createFont("/media/css/Chunkfive-webfont.ttf", 72);
              textFont(font);
              fill(0, 160); // Black with low opacity 
              text("1",  0, 80); 
              text("2", 15, 80); 
              text("3", 30, 80); 
              text("4", 45, 80); 
              text("5", 60, 80);

              We can also use the same trick as before to draw a dropshadow:

              • Show Sketch
              /* @pjs font=/media/css/Chunkfive-webfont.ttf; */
              /** @peep sketchcode */
              size(100, 100);
              background(204);
              PFont font = createFont("/media/css/Chunkfive-webfont.ttf", 16);
              textFont(font);
              background(204);
              String s = "Response is the medium";
              fill(0, 64);
              text(s, 11, 21, 80, 50);
              fill(255);
              text(s, 10, 20, 80, 50);

              Experiment with changing the colour, size and alignment of some text to produce a design.

              Animated Text

              We can animate text in the same way that we can animate anything drawn to the screen. For example, by changing the x-coordinate at which we draw the text over time, we can do simple animations like scroling text across the screen:

              • Show Sketch
              /* @pjs font=/media/css/Chunkfive-webfont.ttf; */
              /** @peep sketchcode */
               
              String scrollingText = "This is a long sentence that I've just written to show you how easy it is to animate text in Processing.";
               
              float x;
              float dx = -1;
               
              void setup() {
                size(200, 200);
                PFont font = createFont("/media/css/Chunkfive-webfont.ttf", 72);
                textFont(font);
                x = width;
              }
               
              void draw() {
                background(204);
                fill(0);
                textAlign(LEFT, CENTER);
                text(scrollingText, x, height/2 + 20);
                x += dx;
                if (x <= -textWidth(scrollingText)) x = 200;
              }

              Notice the use of the textWidth() function to determine the length of the text in the current font, so that the animation can be reset when the text scrolls off the display. This can be a very useful function when we want to lay out text in different fonts.

              Create a simple animation by changing the position of some text on the screen. To start, try modifying the above example to make the text move at a different speed or in a different direction. Remember to change the conditional statements in the draw() function so that it will repeat the animation appropriately.

              Dynamic Typography

              With the use of digital typography in television and film, dynamic typography has become common. This type of animation can be good for telling a story in a dynamic way using words, and has become a common practice in advertising when trying to create an appealing message. Even subtly moving static text (and images) provides visual interest while keeping the message on screen.

              We can use dynamic typography to express properties and behaviours in animated words. For example, we may wish to express the property that a word describes by animating it:

              • Show Code
              /* @pjs font=/media/css/Chunkfive-webfont.ttf; */
              /** @peep sketch */
               
              float y = -30;
              float dy = 1;
               
              void setup() {
                size(200, 200);
                PFont chunkfive = createFont("/media/css/Chunkfive-webfont.ttf", 48);
                textFont(chunkfive);
                textAlign(CENTER, BOTTOM);
                frameRate(20);
              }
               
              void draw() {
                background(204);
                fill(0); 
                text("HEAVY", width/2, y);
                dy *= 1.4;
                y = min((y+dy), height);
                if (frameCount % 50 == 0) {
                  y = -30;
                  dy = 1;
                }
              }

              In this example, we simply animate the word "HEAVY" falling down the screen and landing on the bottom of the display window, without bouncing, as we would expect something heavy to do. Notice that the font that we've chosen to express this property in, is also bold and heavy in its appearance.

              We can also use animation to express a behaviour that we would like to attach to a word. For instance, the following example expresses a nervous behaviour by making the word "nervous" jitter and jump around the centre of the display window. Notice that again, the font is an appropriately untidy one, giving the impression of something being in a rather hurried state.

              • Show Code
              /* @pjs font=/uploads/1/rabiohead.ttf; */
              /** @peep sketch */
              void setup() {
                size(200, 200);
                PFont rabiohead = createFont("/uploads/1/rabiohead.ttf", 48);
                textFont(rabiohead);
                frameRate(20);
              }
               
              void draw() {
                background(204);
                fill(0); 
                textAlign(CENTER, CENTER);
                translate(width/2, height/2);
                rotate(random(-PI/18, PI/18));
                text("nervous", random(-2, 2), random(-2, 2));
              }

              In all of the above examples, it is important to note that when we want to animate text, we don't try to create the font in the draw() function, because this would significantly slow down our animation. Instead we create the font and set it as the current text font in the setup() function. If we want to use multiple fonts, we should load them into variables in the setup() function and only use the textFont() function to switch between them in the draw() function.

              Drawing a Picture Using Animated Words

              The following example shows how to combine multiple fonts into an image that describes an object using words and uses an animation that expresses the behaviour of the object, in this case a burning candle. Notice how we use the noise function in three places, to animate the opacity of the candle to make it appear to flicker, the colour of the flame and the rotation that we apply to the flame.

              • Show Code
              /* @pjs font="/uploads/1/gooddog.otf","/media/css/Chunkfive-webfont.ttf"; */
              /** @peep sketch */
               
              PFont chunkfive, gooddog;
               
              void setup() {
                size(200, 200);
                chunkfive = createFont("/media/css/Chunkfive-webfont.ttf", 16);
                gooddog = createFont("/uploads/1/gooddog.otf", 24);
                frameRate(20);
              }
               
              void draw() {
                background(0);
                textAlign(LEFT, CENTER);
               
                // Draw the candle with varying opacity to give the impression of a flickering light
                fill(255, lerp(128, 255, noise(frameCount * 0.17))); 
                translate(width/2, height - 20);
                rotate(-PI/2);
                textFont(chunkfive);
                text("CANDLE", 0, 0);
               
                // Move to the end of the candle
                translate(textWidth("CANDLE"), 0);
                // Scale, rotate and colour the word "flame" to express the movement of the 
                rotate(lerp(-PI/9, PI/18, noise(frameCount * 0.059)));
                scale(lerp(1, 1.2, noise(frameCount * 0.071)));
                fill(lerpColor(color(128, 0, 0), color(255, 192, 0), noise(frameCount * 0.17)));
                textFont(gooddog);
                text("flame", 0, 0);
              }

              Create a sketch that draws a picture using dynamic typography that expresses the properties and behaviours of an object.

              Comments