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.
- concatenation :: The + sign is used to combine, or concatenate, Strings together.
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
- comparison :: Relational operators are used to compare Strings.
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
- character count :: We can find the length of a String by calling the length() method on it. Note that spaces are counted as characters. (We will look at this notation in depth in the next section.)
println(dString.length()); // writes "13" to the console
- char extraction :: We can get the char at a particular location of the String using String.charAt(index).
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:
- Declare a variable of type PFont.
PFont f;
-
Load a font into that variable using loadFont("name_of_font_file")
- This font must be in the special format used by Processing, with extension .vlw. You can convert an existing font to the .vlw format by selecting Tools:Create Font... from the Processing menu bar.
- The font can also be compressed using gzip. This is why some fonts that come with Processing end with .gz.
- The properly formatted font must be placed in the data folder of the sketch.
f = loadFont("Skia-48.vlw");
- Set the active font to be the one we just loaded, and specify the point size using textFont(fontVar, size).
textFont(f, 24);
-
Write to the display using text(data , xPos , yPos), where
- data is a String, char, int or float.
- the coordinates are ints or floats.
text("I am a banana", 50, 50);
You can also use the following built-in functions to modify the appearance of the text:
- textSize() :: sets the size of the displayed font.
- textLeading() :: sets the spacing between lines of text.
- textAlign() :: sets the alignment for drawing 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;
}
}