Processing Beginner Article 6

Text & Typography

Draw, measure, and animate text in Processing using PFont and kinetic typography techniques.

⏱ 18 min text PFont typography animation kinetic textAlign

Basic text

text() draws a string at a given position. By default text is drawn with its baseline at the y coordinate and its left edge at x.

void setup() {
  size(600, 200);
  background(20);
}

void draw() {
  background(20);
  fill(255);
  textSize(48);
  text("Hello, Processing!", 40, 120);
}

text() respects the current fill() colour. You can draw coloured, transparent, or even stroked text by setting fill and stroke before the call.

textSize and textAlign

textSize(24);               // set font size in pixels

textAlign(CENTER, CENTER);  // horizontal: LEFT / CENTER / RIGHT
                            // vertical:   TOP / CENTER / BOTTOM / BASELINE

// Now coordinates are the centre of the text bounding box
text("Centred", width / 2, height / 2);

textAlign(CENTER, CENTER) is particularly useful when you want to position text relative to a shape’s centre rather than its baseline corner.

Loading fonts: loadFont and createFont

Processing can use any font installed on your system via createFont(), or use a pre-processed .vlw bitmap font created through the Tools → Create Font menu.

PFont mono;
PFont serif;

void setup() {
  size(600, 300);
  background(15);

  // createFont loads a system font at a given size
  mono  = createFont("Courier New", 24);
  serif = createFont("Georgia", 32);
}

void draw() {
  background(15);

  textFont(mono);
  fill(120, 220, 120);
  text("monospaced courier", 40, 100);

  textFont(serif);
  fill(220, 150, 80);
  text("Georgia serif", 40, 180);
}

For maximum quality in exported PDFs or high-resolution output, generate .vlw fonts via Tools → Create Font and load them with loadFont("MyFont-32.vlw").

Measuring text

Three built-in functions let you measure text at the current font and size:

String msg = "Processing";
float w = textWidth(msg);           // width in pixels
float asc = textAscent();           // height above baseline
float desc = textDescent();         // depth below baseline
float totalH = asc + desc;

// Draw a bounding box around the text
float tx = 50, ty = 150;
fill(255);
text(msg, tx, ty);

noFill();
stroke(255, 80, 80);
rect(tx, ty - asc, w, totalH);

These measurements are essential for text-based UI elements, speech bubbles, and any layout where text must be aligned with other objects.

Drawing text along a curve

By calculating a point on a circle for each character, you can arrange text in an arc:

String msg  = "* CIRCULAR TEXT IN PROCESSING *";
float radius = 180;

void setup() {
  size(500, 500);
}

void draw() {
  background(15);
  textAlign(CENTER, CENTER);
  textSize(18);
  fill(200, 220, 255);
  noStroke();

  float totalAngle = TWO_PI;
  float step = totalAngle / msg.length();

  for (int i = 0; i < msg.length(); i++) {
    float angle = step * i - HALF_PI;  // start at top
    float x = width  / 2 + cos(angle) * radius;
    float y = height / 2 + sin(angle) * radius;

    pushMatrix();
    translate(x, y);
    rotate(angle + HALF_PI);  // rotate each letter to face outward
    text(msg.charAt(i), 0, 0);
    popMatrix();
  }
}

Each character is extracted with msg.charAt(i) and drawn individually with a pushMatrix/rotate/popMatrix wrapper so it faces the correct direction.

Full example: animated kinetic typography

In kinetic typography, letters move independently. This sketch breaks a word into individual Letter objects, each drifting and returning to its home position.

import java.util.ArrayList;

ArrayList<Letter> letters = new ArrayList<Letter>();
String WORD = "PROCESS";

void setup() {
  size(700, 400);
  textAlign(CENTER, CENTER);

  PFont f = createFont("Arial Bold", 80);
  textFont(f);

  // Calculate the total width so we can centre the word
  float totalW = 0;
  for (int i = 0; i < WORD.length(); i++) {
    totalW += textWidth(WORD.charAt(i));
  }

  // Position each letter
  float x = (width - totalW) / 2;
  float y = height / 2;
  for (int i = 0; i < WORD.length(); i++) {
    char c = WORD.charAt(i);
    float cw = textWidth(c);
    letters.add(new Letter(c, x + cw / 2, y));
    x += cw;
  }
}

void draw() {
  background(15);

  for (Letter l : letters) {
    l.update();
    l.display();
  }
}

// Click to scatter the letters
void mousePressed() {
  for (Letter l : letters) {
    l.scatter();
  }
}

class Letter {
  char c;
  float homeX, homeY;   // resting position
  float x, y;           // current position
  float vx, vy;         // velocity

  Letter(char c, float hx, float hy) {
    this.c = c;
    homeX = hx;  homeY = hy;
    x = hx;      y = hy;
    vx = 0;      vy = 0;
  }

  void scatter() {
    vx = random(-8, 8);
    vy = random(-12, -4);
  }

  void update() {
    // Spring back toward home position
    float ax = (homeX - x) * 0.06;
    float ay = (homeY - y) * 0.06 + 0.3;  // gravity
    vx = (vx + ax) * 0.88;
    vy = (vy + ay) * 0.88;
    x += vx;
    y += vy;
  }

  void display() {
    float d = dist(x, y, homeX, homeY);
    fill(map(d, 0, 200, 220, 80),
         map(d, 0, 200, 220, 120),
         255);
    noStroke();
    text(c, x, y);
  }
}

Click to scatter the letters; they spring back with simulated gravity and damping. The colour shifts from near-white (at rest) toward blue-purple (displaced), giving instant visual feedback about each letter’s distance from home.

Key takeaways

  • text(str, x, y) draws at the baseline-left; use textAlign(CENTER, CENTER) to centre on a point.
  • createFont("FontName", size) loads any installed system font.
  • textWidth(), textAscent(), and textDescent() let you measure strings precisely.
  • Draw text along a curve by computing per-character positions and rotating with pushMatrix/rotate/popMatrix.
  • Kinetic typography is achieved by treating each character as an independent animated object.