fontoutline

versions0095+
contributorsdavebollinger
started on2007-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.

Source code

/**
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
 
}

Demo Usage

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:

fontnoise.jpg

/**
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); 
    }
  }
}

Downloads

Download includes both sources listed above: font_noise.zip

hacks/fontoutline.txt · Last modified: 2008-05-31 02:16 (external edit)