The following version of the getShape() function will run in Processing with the default window without using java components. It’s important to use the P2D renderer to get the desired output. A few additions to the original function were made to get the vectors and translate the points into the window.
import java.awt.Font;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
PShape myShape;
PFont processingFont;
// Array added to temporarily hold coordinates
double[] coords = new double[2];
public PShape getShape(char ch, float detail) {
Font font = (Font) processingFont.getNative();
if (font == null) {
throw new IllegalArgumentException("getShape() only works on fonts loaded with createFont()");
}
// PShape s = new PShape(PShape.PATH);
// This was added
PShape s = createShape();
// six element array received from the Java2D path iterator
float[] iterPoints = new float[6];
// array passed to createGlyphVector
char[] textArray = new char[] { ch };
//Graphics2D graphics = (Graphics2D) this.getGraphics();
//FontRenderContext frc = graphics.getFontRenderContext();
@SuppressWarnings("deprecation")
FontRenderContext frc =
Toolkit.getDefaultToolkit().getFontMetrics(font).getFontRenderContext();
GlyphVector gv = font.createGlyphVector(frc, textArray);
Shape shp = gv.getOutline();
// make everything into moveto and lineto
PathIterator iter = (detail == 0) ?
shp.getPathIterator(null) : // maintain curves
shp.getPathIterator(null, detail); // convert to line segments
// This was added to translate path down into window
AffineTransform translate = new AffineTransform();
translate.setToTranslation(250, 150);
PathIterator path = shp.getPathIterator(translate, 0.5);
while (!path.isDone()) {
path.currentSegment(coords);
circle((int)coords[0], (int)coords[1], 4);
path.next();
}
int contours = 0;
while (!iter.isDone()) {
int type = iter.currentSegment(iterPoints);
switch (type) {
case PathIterator.SEG_MOVETO: // 1 point (2 vars) in textPoints
if (contours == 0) {
s.beginShape();
} else {
s.beginContour();
}
contours++;
s.vertex(iterPoints[0], iterPoints[1]);
break;
case PathIterator.SEG_LINETO: // 1 point
s.vertex(iterPoints[0], iterPoints[1]);
break;
case PathIterator.SEG_QUADTO: // 2 points
s.quadraticVertex(iterPoints[0], iterPoints[1],
iterPoints[2], iterPoints[3]);
break;
case PathIterator.SEG_CUBICTO: // 3 points
s.bezierVertex(iterPoints[0], iterPoints[1],
iterPoints[2], iterPoints[3],
iterPoints[4], iterPoints[5]);
break;
case PathIterator.SEG_CLOSE:
if (contours > 1) {
s.endContour();
}
break;
}
iter.next();
}
s.endShape(CLOSE);
return s;
}
void setup() {
size(400, 400, P2D); // Note use of P2D renderer; IMPORTANT!
processingFont = createFont("Webdings", 106); // Should work for other fonts, esp Wingdings
fill(12, 135, 155); // teal; use whatever color you want
//range 33 - 255 use char(int) or char('a..z' or 'A..Z' or '!@#$') keys from keyboard
myShape = getShape(char('!'), 0.5);
println(myShape);
}
void draw() {
scale(2.0);
shape(myShape, 50, 150);
}