internal text representations

char

The primitive data type for handling single letters, numbers, and symbols ($, *, !, &, ...) is called char.

// char variable declaration and initialization
// note the use of single quotes
char aChar = 'a'; 
char bChar = 'b';

char tempChar;

tempChar = aChar;             

A char is actually very similar to an int. It is also an integer, but it is 1 byte long (8 bits :: from 0 to 255), interpreted as an ASCII value. In fact, chars and ints are interchangeable in some cases. If we look at the pulses example, we used the spacebar to clear the screen using this code:

void keyPressed() {
  if (key == 32) {  // space bar
    // clear all
    numPulses = 0;
  } 
}

We can achieve the same functionality using the char representing a space:

void keyPressed() {
  if (key == ' ') {
    // clear all
    numPulses = 0;
  } 
}

Similarly, if we were capturing the letter a, we could either check if key was equal to 'a' or if it was equal to its ASCII value 97.

String

The data object for handling sequences of chars is called String. A String is essentially a sequence of chars with special properties and functions that can be used within it.

Strings are declared and assigned in the same way as all the other data types we have seen so far.

// String variable declaration and initialization
// note the use of double quotes
String aString = "I am";
String bString = "a banana";     

String tempString;

tempString = aString;         

There are also additional operations we can perform on Strings.

String cString = aString + bString;
println(cString);  // writes "I ama banana" to the console

String dString = aString + " " + bString;
println(dString);  // writes "I am a banana" to the console
println(aString == bString);  // writes "false" to the console   
println(aString == "I am");   // writes "true" to the console   
println(aString != bString);  // writes "true" to the console
println(dString.length());  // writes "13" to the console   
char c = dString.charAt(3);   
println(c);  // writes "m" to the console

A whole host of other functions that operate on Strings can be found here.

fonts

In order to write text to the display window, we have to go through several steps:

PFont f;
f = loadFont("Skia-48.vlw");
textFont(f, 24);
text("I am a banana", 50, 50);

You can also use the following built-in functions to modify the appearance of the text:

reading text from a file

If we want to read text from an external file, we can use loadStrings("name_of_text_file"). Just like all other external files, the text file in question must be in the data folder of the sketch. loadStrings() breaks the text file apart into a String array, creating a new element for each line of text.

Here is an example of a text brush. It loads the text from an external file, and when the user drags the mouse, it writes a line from the file at the mouse position. Each mouse drag advances through the text file, and when the end of the file is reached it will start over again.

PFont f;
String[] textFile;  // contents of external file split by line
int textIndex = 0;  // tracks the current location in the textFile array

void setup() {
  size(400, 400);
  smooth();
  frameRate(30);
  background(0);

  // load and set the font
  f = loadFont("Skia-48.vlw");
  textFont(f, 12);

  // load the contents of the external file into the String array
  textFile = loadStrings("hamsters.txt");
  
  fill(255);
}

void draw() {
  // keep the motor running
}

void mouseDragged() {
  sprayText();
}

void keyPressed() {
  if (key == ' ') {
    // clear screen
    background(0);
  } 
}

/* writes a line of text at the mouse position */
void sprayText() {
  text(textFile[textIndex], mouseX, mouseY);
  textIndex++;

  // if we reach the end of the array, reset index to the beginning
  if (textIndex >= textFile.length) {
    textIndex = 0;
  }
}

If we want to modify the brush so that it sprays words instead of entire lines, we would need to change textFile so that each element in it is a word. The first step in doing this would be to use join(), which combines an array of Strings into a single String. The second parameter to join() is a char or String that will go between each element in the String array. For example, if the array holds the 2 elements me and you, and the separator is a -, then the joined String would be me-you. The next step would be to split() the String into an array of words, i.e. every time we encounter a space.

PFont f;
String[] textFile;  // contents of external file split by word
int textIndex = 0;  // tracks the current location in the textFile array

void setup() {
  size(400, 400);
  smooth();
  frameRate(30);
  background(0);

  // load and set the font
  f = loadFont("Skia-48.vlw");
  textFont(f, 12);

  // load the contents of the external file into the String array
  String[] linesFile = loadStrings("hamsters.txt");
  // join the lines, placing a space between each entry
  String allText = join(linesFile, " ");
  // split the text every time there is a space
  textFile = split(allText, " ");

  fill(255);
}

void draw() {
  // keep the motor running
}

void mouseDragged() {
  sprayText();
}

void keyPressed() {
  if (key == ' ') {
    // clear screen
    background(0);
  } 
}

/* writes a word at the mouse position */
void sprayText() {
  text(textFile[textIndex], mouseX, mouseY);
  textIndex++;
  
  // if we reach the end of the array, reset index to the beginning
  if (textIndex >= textFile.length) {
    textIndex = 0;
  }
}

We can modify the brush once more so that it paints individual characters instead of words. The first idea that comes to mind would be to proceed as we just did with the join() and then split() for every character, i.e. for any delimiter.

// load the contents of the external file into the String array
String[] linesFile = loadStrings("hamsters.txt");
// join the lines, placing a space between each entry
String allText = join(linesFile, " ");
// split the text for every character
textFile = split(allText, "");

However, we can do this in a cleaner way. Since chars are just numbers that are 1 byte long, we can load them from the file using loadBytes(), which will return a byte array, which is almost identical to a char array. In fact, the only difference is that we need to explicitly tell Processing to interpret the bytes as chars, and this is done using the char() conversion function.

PFont f;
byte[] textFile;    // contents of external file split by character
int textIndex = 0;  // tracks the current location in the textFile array

void setup() {
  size(400, 400);
  smooth();
  frameRate(30);
  background(0);

  // load and set the font
  f = loadFont("Skia-48.vlw");
  textFont(f, 12);

  // load the contents of the external file into the byte array
  textFile = loadBytes("hamsters.txt");

  fill(255);
}

void draw() {
  // keep the motor running
}

void mouseDragged() {
  sprayText();
}

void keyPressed() {
  if (key == ' ') {
    // clear screen
    background(0);
  } 
}

/* writes a character at the mouse position */
void sprayText() {
  text(char(textFile[textIndex]), mouseX, mouseY);
  textIndex++;
  
  // if we reach the end of the array, reset index to the beginning
  if (textIndex >= textFile.length) {
    textIndex = 0;
  }
}

Processing Workshop

Elie Zananiri
Alberta College of Art + Design
3-5 April 2008