| versions | 0095+ |
|---|---|
| contributors | davebollinger |
| started on | 2007-09-03 11:27 |
Presented below is one method for retrieving the outline of a string of text as rendered with a particular font. The path returned can then be used in many different ways within a sketch.
/** fontoutline taken from http://processinghacks.com/hacks:fontoutline @author David Bollinger */ // FontOutlineSystem.pde // Dave Bollinger, Aug 2007 // purpose: to convert a string of text in a specified font into // a usable list of points represeting its outline import java.awt.Font; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.Graphics2D; import java.awt.geom.Point2D; import java.awt.geom.PathIterator; import java.awt.Image.BufferedImage; import java.awt.Shape; /** * Represents one stroke of a glyph. Glyphs typically * look like MOVE,DRAW,DRAW,DRAW,...,DRAW,CLOSE - no * need to distinguish between draw and close as they're * both effectively draw strokes. */ class FontPoint { static final int MOVE = PathIterator.SEG_MOVETO; static final int DRAW = PathIterator.SEG_LINETO; float x, y; int mode; FontPoint() { this(0f,0f,MOVE); } FontPoint(float x, float y) { this(x,y,MOVE); } FontPoint(float x, float y, int mode) { this.x = x; this.y = y; this.mode = mode; } } class FontOutlineSystem { PApplet applet; Font font; BufferedImage img; Graphics2D g2d; FontRenderContext frc; FontOutlineSystem(PApplet applet) { this(applet,"",12); } FontOutlineSystem(PApplet applet, String fontName, int fontSize) { this.applet = applet; // we need a Graphics2D... if (applet.g.getClass().getName().equals("PGraphicsJava2D")) { // JAVA2D has one of it's own already: g2d = ((PGraphicsJava2D)g).g2; } else { // P3D, OPENGL don't have one, so make one: img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); g2d = img.createGraphics(); } frc = g2d.getFontRenderContext(); loadFont(fontName, fontSize); } void loadFont(String name, int size) { font = new Font(name, Font.PLAIN, size); } /** * Returns an array list containing FontPoint's that * represent the outline of the specified text at * specified origin. */ ArrayList convert(String text, float xo, float yo) { ArrayList al = new ArrayList(); if (font==null) return al; float [] seg = new float[6]; float x=0, y=0, mx=0, my=0; GlyphVector gv = font.createGlyphVector(frc, text); Shape glyph = gv.getOutline(xo, yo); PathIterator pi = glyph.getPathIterator(null); while (!pi.isDone()) { int segtype = pi.currentSegment(seg); int mode = 0; switch(segtype) { case PathIterator.SEG_MOVETO: x = mx = seg[0]; y = my = seg[1]; mode = FontPoint.MOVE; break; // as written, all this code cares about are the endpoints, // quadratic and cubic curves are not interpolated, so all // three can be handled by the same code: case PathIterator.SEG_LINETO: case PathIterator.SEG_QUADTO: case PathIterator.SEG_CUBICTO: x = seg[0]; y = seg[1]; mode = FontPoint.DRAW; break; case PathIterator.SEG_CLOSE: x = mx; y = my; mode = FontPoint.DRAW; break; } // switch al.add(new FontPoint(x,y,mode)); pi.next(); } // while return al; } // convert }
Now that you can convert your text into a list of points, it's time to DO something with those points! The possibilities are endless, but here's a simple one just to give you the feel for how to use the above class:
/** fontoutline taken from http://processinghacks.com/hacks:fontoutline @author David Bollinger */ FontOutlineSystem fos; ArrayList path; void setup() { size(600,200,JAVA2D); smooth(); fos = new FontOutlineSystem(this); fos.loadFont("Lucida Bright", 100); path = fos.convert("Font Noise", 50, 130); background(255); } void draw() { fill(255,8); noStroke(); rect(0,0,width,height); stroke(0); float t = frameCount * 0.1; float x=0, y=0, ox=0, oy=0; for (int i=0, n=path.size(); i<n; i++) { FontPoint fp = (FontPoint)path.get(i); ox = x; oy = y; x = fp.x + noise(t, i) * 20f - 10f; y = fp.y + noise(t, i) * 20f - 10f; if (fp.mode==FontPoint.DRAW) { line(ox,oy,x,y); } } }
Download includes both sources listed above: font_noise.zip