// A demonstration of text processing in the form of a // speed-reading application, somewhat akin to Spritz. // // Author: Michael Goldwasser // contstants that can be tuned int WORDS_PER_MINUTE = 1000; int FONTSIZE = 70; //String sourcefile = "http://www.gutenberg.org/cache/epub/2591/pg2591.txt"; int NUM_SAMPLES = 9; int num = int(1 + random(NUM_SAMPLES)); String sourcefile = "example" + num + ".txt"; // globals used to store text and progress String[] words; // will be loaded from file int cur=0; // index of current word boolean running = false; // global to help with font metric float tickMarkX; // x-coordinate of tick mark for placing word float baseline; // We want canvas size to depend on FONTSIZE, but Processing 3 will not // allow variable size within setup. void settings() { size(13*FONTSIZE, 3*FONTSIZE); } void setup() { textSize(FONTSIZE); frameRate(WORDS_PER_MINUTE/60.0); background(255); strokeWeight(2); tickMarkX = 0.33*width; baseline = 2*FONTSIZE - textDescent(); line(0, 0.1*FONTSIZE, width, 0.1*FONTSIZE); line(0, 2.9*FONTSIZE, width, 2.9*FONTSIZE); line(tickMarkX, 0.1*FONTSIZE, tickMarkX, 0.5*FONTSIZE); line(tickMarkX, 2.5*FONTSIZE, tickMarkX, 2.9*FONTSIZE); loadTextFile(sourcefile); renderWord("Click to Begin"); } // used to (re)start the rendering of the prose void mouseClicked() { running = !running; if (cur == words.length) { cur = 0; // start over } } void draw() { if (running) { renderWord(words[cur]); cur++; if (cur == words.length) { running = false; } } } // Display a single word to be read void renderWord(String word) { noStroke(); fill(255); rect(0, 0.5*FONTSIZE, width, 2*FONTSIZE); // divide word into three portions (left, middle, right). int divide = getRedIndex(word.length()); String left = word.substring(0, divide); String middle = word.substring(divide, 1+divide); String right = word.substring(1+divide); // until the end textAlign(CENTER); fill(255, 0, 0); // red character text(middle, tickMarkX, baseline); fill(0); // black characters textAlign(RIGHT); text(left, tickMarkX - 0.5 * textWidth(middle), baseline); textAlign(LEFT); text(right, tickMarkX + 0.5 * textWidth(middle), baseline); } // Open a text file and break its text into individual words, // as separated by spaces. Those words are loaded into the // global 'words' array. void loadTextFile(String filename) { String[] lines = loadStrings(filename); // first, let's count the total number of words in document int total = 0; for (int j=0; j < lines.length; j++) { total += splitTokens(lines[j]).length; } // Now let's resize global array of words and fill it words = new String[total]; int w=0; // index into words for (int j=0; j < lines.length; j++) { String[] pieces = splitTokens(lines[j]); for (int k=0; k < pieces.length; k++) { words[w] = pieces[k]; w++; } } } // Given a particular word length, return index of character that becomes red int getRedIndex(int length) { return (length + 2) / 4; // integer division }