/*
fractype.java
copyright 1990,2001 Bill Prewitt
Inspired by the "COKE" illustration on page 100 of "Fractals Everywhere",
1st edition,by Michael Barnsley, 1988, Academic Press
Written in MS Quick C 2.5 in 1990, then ported to Java Applet in 2001
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.io.*;
import java.lang.String;
import java.util.Random;
/*
*/
public class fractype02 extends Applet
implements ActionListener {
// TextField scrwidth;
// TextField scrheight;
TextField myword;
CheckboxGroup iterationSet;
Button updateButton;
public void init() {
this.setBackground(Color.white);
// Label scrwidthp = new Label("Width (pixels): ",Label.RIGHT);
// scrwidth= new TextField("800");
// add(scrwidthp);
// add(scrwidth);
// Label scrheightp = new Label("Height (pixels): ",Label.RIGHT);
// scrheight= new TextField("600");
// add(scrheightp);
// add(scrheight);
Label mywordp = new Label("Word: ",Label.LEFT);
myword= new TextField(10);
myword.setText("beer");
add(mywordp);
add(myword);
Label iterationp = new Label("Iterations: ",Label.LEFT);
iterationSet = new CheckboxGroup();
add(iterationp);
add(new Checkbox("20000",iterationSet,true));
add(new Checkbox("80000",iterationSet,false));
add(new Checkbox("500000",iterationSet,false));
updateButton = new Button("Draw");
add(updateButton);
// register to receive action events
updateButton.addActionListener(this); // press the button
myword.addActionListener(this); // Enter the word
// scrwidth.addActionListener(this);
// scrheight.addActionListener(this);
}
// User pressed Enter or clicked button or whatever was registered above
public void actionPerformed(ActionEvent ae) {
repaint();
}
public void paint( Graphics g) {
g.drawString(" ************* F R A C T Y P E ******************* ",10,40);
g.drawString(" A fractal font rendering program ",10,60);
g.drawString(" written by Bill Prewitt 13 Nov 1990, rewritten as Java applet 11 Dec 2001 ",10,80);
rifs(g, myword); // Random Iterated Function Set
g.drawString(" .... done ",10,570);
}
//public void rifs (Graphics g, TextField scrwidth, TextField scrheight, TextField myword)
public void rifs (Graphics g, TextField myword)
{
double x=0. , y=0. , newx=0., newy=0. ;
int i , j, k, l, m, n, ix, iy ;
int nstrokes ;
double p0, p1, p2, p3, p4, p5, p6, p7, p8, p9 ;
double p10, p11, p12, p13, p14, p15, p16, p17, p18, p19 ;
double p20, p21, p22, p23, p24, p25, p26, p27, p28, p29 ;
double p30, p31, p32, p33, p34, p35, p36, p37, p38, p39 ;
// BUG Here - this is only good for 40 strokes - then it blows up.
double a[],b[],c[],d[],e[],f[],p[];
a = new double[40];
b = new double[40];
c = new double[40];
d = new double[40];
e = new double[40];
f = new double[40];
p = new double[40];
double a11 = -.0015625 ;
double a12 = .0015625 ;
double a13 = 0. ;
double a21 = -.00104166 ;
double a22 = -.00104166 ;
double a23 = .00208333 ;
double a31 = 1. ;
double a32 = 0. ;
double a33 = 0. ;
double dotx[][], doty[][] ;
dotx = new double[40][3] ;
doty = new double[40][3] ;
char charnam[] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','.','-','!','?'} ;
int charstrokes[] = {3,6,3,4,4,3,4,3,1,3,3,2,4,3,4,4,5,5,5,2,3,2,4,2,3,3,1,1,2,5,0,0,0} ;
// (sum is 97) a b c d e f g h i j k l m n o p q r s t u v w x y z . - ! ?
int charofs[] ;
charofs = new int[32] ;
double charkern[];
charkern = new double[32];
double maxkern, avgkern ;
int nchar, letrno, istroke ;
char letr ;
double ymult, xmult, xofs ;
double fontstroke[][] = {
// this array is x0,y0,x1,y1,x2,y2 (three points define stroke area)
// lay it out on graph paper in a 100x100 grid
// A3
{20.,0.,40.,100.,10.,50.},
{80.,0.,45.,100.,40.,55.},
{25.,15.,60.,15.,40.,35.},
// B6
{30.,0.,30.,100.,0.,50.},
{20.,80.,70.,80.,40.,100.},
{20.,40.,70.,40.,40.,60.},
{20.,0.,70.,0.,40.,20.},
{60.,95.,60.,50.,75.,70.},
{60.,45.,60.,05.,75.,20.},
// C3
{30.,0.,30.,100.,0.,50.},
{20.,80.,70.,80.,40.,100.},
{20.,0.,70.,0.,40.,20.},
// D4
{30.,0.,30.,100.,0.,50.},
{20.,85.,70.,70.,40.,90.},
{60.,80.,60.,10.,80.,50.},
{20.,0.,70.,10.,40.,20.},
// E4
{0.,20.,0.,80.,20.,50.},
{0.,80.,70.,80.,35.,100.},
{20.,40.,60.,40.,40.,60.},
{0.,0.,80.,0.,40.,20.},
// F3
{30.,0.,30.,100.,0.,50.},
{25.,80.,70.,80.,40.,100.},
{25.,40.,50.,40.,35.,60.},
// G4
{30.,0.,30.,100.,0.,50.},
{20.,80.,70.,80.,40.,100.},
{50.,40.,50.,10.,70.,30.},
{20.,0.,70.,0.,40.,20.},
// H3
{30.,0.,30.,100.,0.,50.},
{50.,0.,50.,100.,80.,50.},
{25.,30.,55.,30.,40.,50.},
// I1
{30.,0.,30.,100.,10.,50.},
// J3
{70.,10.,70.,100.,40.,50.},
{10.,0.,65.,0.,30.,20.},
{0.,40.,0.,10.,20.,25.},
// K3
{30.,0.,30.,100.,0.,50.},
{25.,50.,70.,80.,35.,80.},
{25.,50.,50.,00.,60.,35.},
// L2
{0.,100.,0.,10.,20.,55.},
{0.,0.,65.,0.,35.,20.},
// M4
{0.,0.,30.,0.,15.,100.},
{60.,0.,90.,0.,75.,100.},
{20.,75.,35.,40.,40.,70.},
{45.,40.,70.,80.,50.,70.},
// N3
{20.,0.,20.,100.,0.,60.},
{20.,80.,50.,0.,50.,60.},
{50.,100.,50.,0.,70.,60.},
// O4
{20.,0.,20.,100.,0.,50.},
{50.,100.,50.,0.,70.,50.},
{10.,80.,60.,80.,35.,100.},
{10.,0.,60.,0.,35.,20.},
// P4
{30.,0.,30.,100.,0.,50.},
{10.,80.,60.,80.,35.,100.},
{50.,90.,50.,50.,70.,70.},
{15.,40.,60.,40.,40.,60.},
// Q5
{20.,40.,55.,80.,20.,70.},
{30.,85.,60.,50.,70.,80.},
{70.,60.,30.,20.,65.,30.},
{40.,20.,15.,50.,15.,25.},
{50.,15.,60.,0.,70.,15.},
// R5
{30.,0.,30.,100.,0.,50.},
{05.,80.,60.,80.,40.,100.},
{50.,90.,50.,50.,70.,70.},
{15.,40.,50.,40.,40.,60.},
{45.,40.,65.,0.,70.,30.},
// S5
{10.,80.,60.,80.,40.,100.},
{30.,50.,30.,90.,0.,70.},
{15.,40.,50.,40.,40.,60.},
{40.,50.,40.,10.,70.,30.},
{00.,00.,60.,00.,30.,20.},
// T2
{25.,0.,45.,0.,35.,80.},
{0.,80.,70.,80.,35.,100.},
// U3
{20.,10.,20.,100.,0.,60.},
{50.,100.,50.,10.,70.,60.},
{10.,0.,60.,0.,35.,20.},
// V2
{0.,85.,25.,0.,30.,60.},
{40.,0.,70.,80.,40.,60.},
// W4
{0.,90.,15.,0.,30.,50.},
{80.,0.,90.,95.,60.,50.},
{30.,0.,50.,60.,30.,35.},
{40.,50.,60.,0.,60.,30.},
// X2
{60.,0.,0.,95.,50.,60.},
{25.,0.,80.,100.,30.,55.},
// Y3
{30.,0.,50.,0.,40.,60.},
{0.,90.,30.,60.,30.,80.},
{50.,60.,80.,90.,50.,80.},
// Z3
{0.,80.,80.,80.,40.,100.},
{20.,0.,75.,80.,35.,60.},
{0.,0.,80.,0.,40.,20.},
// .
{0.,0.,20.,0.,20.,20.},
// -
{10.,40.,60.,40.,35.,60.},
// !
{5.,0.,25.,0.,15.,20.},
{0.,30.,30.,30.,15.,100.},
// ?
{20.,0.,40.,0.,30.,20.},
{25.,20.,70.,50.,30.,50.},
{50.,50.,70.,50.,60.,90.},
{10.,80.,60.,80.,35.,100.},
{0.,70.,20.,70.,10.,90} } ;
char buf[] ;
String inWord;
String upperWord;
Random rand = new Random();
char bitmask, bytout;
long count = Long.parseLong(iterationSet.getSelectedCheckbox().getLabel());
// String sscrwidth = scrwidth.getText();
// String sscrheight = scrheight.getText();
// Integer nscrwidth=Integer.valueOf(sscrwidth);
// Integer nscrheight=Integer.valueOf(sscrheight);
inWord=myword.getText();
upperWord=inWord.toUpperCase();
char mychar = '?';
char isay[] = {'?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?'};
nchar=upperWord.length();
for (i = 0; i < nchar; i++){
mychar=upperWord.charAt(i);
isay[i]=mychar;
}
// g.drawString(" The rifs WIDTH is: " + nscrwidth,10,240);
// g.drawString(" The rifs HEIGHT is: " + nscrheight,10,260);
// g.drawString(" The rifs WORD is: " + upperWord,10,280);
// g.drawString(" nchar is: "+nchar ,10,300);
// derive some arrays from the stroke maps
charofs[0] = (int) 0 ;
for(i = 1; i < 32; i++){
charofs[i] = charofs[i-1] + charstrokes[i-1] ;
}
// charkern array is max X in each letter
for(i = 0; i < 32; i++){
j=charofs[i];
charkern[i] = 0. ;
for (k = 0; k < charstrokes[i]; k++){
// find max X in each of 3 points in each stroke of each letter
if(fontstroke[j+k][0] > charkern[i] )
charkern[i] = fontstroke[j+k][0] ;
if(fontstroke[j+k][2] > charkern[i] )
charkern[i] = fontstroke[j+k][2] ;
if(fontstroke[j+k][4] > charkern[i] )
charkern[i] = fontstroke[j+k][4] ;
}
}
// calculate maxkern = total character cell width requested
maxkern = 0. ;
avgkern = 0. ;
for( i = 0; i < nchar; i++){
letr = upperWord.charAt(i) ;
// g.drawString(" letr: "+ letr,500,320+20*i);
for( letrno = 0; letrno < 33; letrno++){
if(letr == charnam[letrno]) break ;
}
// we broke out with either a match or 32,
// but 32 points to white space
// BUG here - blows up if no match
// g.drawString(" maxkern,avgkern,nchar: "+ maxkern+avgkern+nchar,300,340+20*i);
maxkern = maxkern + charkern[letrno] ;
avgkern = maxkern / nchar ;
}
// initialize & calculate cell multipliers to fit screen
// each letter was mapped into 100x100 cell: map into nscrheight x nscrwidth screen
ymult = 4.8 ;
xofs = 0. ;
xmult = 640./((avgkern+5.) * nchar) ;
// look up strokes for each character, scale & put in dot arrays
nstrokes = 0 ;
for( i = 0; i < nchar; i++){
letr = isay[i] ;
for( letrno = 0; letrno < 33; letrno++){
if(letr == charnam[letrno]) break ;
}
// we broke out with either a match or 32,
// but 32 points to white space
// BUG here - blows up if no match
// g.drawString(" letrno: "+ letrno,500,320+20*i);
for( j = 0; j < charstrokes[letrno]; j++){
istroke = charofs[letrno] + j ;
dotx[nstrokes][0] = fontstroke[istroke][0] * xmult + xofs ;
dotx[nstrokes][1] = fontstroke[istroke][2] * xmult + xofs ;
dotx[nstrokes][2] = fontstroke[istroke][4] * xmult + xofs ;
doty[nstrokes][0] = fontstroke[istroke][1] * ymult ;
doty[nstrokes][1] = fontstroke[istroke][3] * ymult ;
doty[nstrokes][2] = fontstroke[istroke][5] * ymult ;
nstrokes++ ;
}
xofs = xofs + xmult * charkern[letrno] + 10. ;
// g.drawString(" nstrokes,xofs: "+nstrokes+"|"+xofs,400,320+20*i);
}
for ( i=0 ; i<40 ; i++){
p[i] = 0. ;
}
for ( i = 0; i < nstrokes; i++){
// scale: multiply by inverted full screen
a[i] = dotx[i][0] * a11 + dotx[i][1] * a12 + dotx[i][2] * a13 ;
b[i] = dotx[i][0] * a21 + dotx[i][1] * a22 + dotx[i][2] * a23 ;
c[i] = doty[i][0] * a11 + doty[i][1] * a12 + doty[i][2] * a13 ;
d[i] = doty[i][0] * a21 + doty[i][1] * a22 + doty[i][2] * a23 ;
e[i] = dotx[i][0] ;
f[i] = doty[i][0] ;
p[i] = 1. / nstrokes ; // should be weighted by area of stroke
}
x= 0. ;
y= 0. ;
p0= p[0]*32768 ;
p1= p0+p[1]*32768 ;
p2= p1+p[2]*32768 ;
p3= p2+p[3]*32768 ;
p4= p3+p[4]*32768 ;
p5= p4+p[5]*32768 ;
p6= p5+p[6]*32768 ;
p7= p6+p[7]*32768 ;
p8= p7+p[8]*32768 ;
p9= p8+p[9]*32768 ;
p10= p9+p[10]*32768 ;
p11= p10+p[11]*32768 ;
p12= p11+p[12]*32768 ;
p13= p12+p[13]*32768 ;
p14= p13+p[14]*32768 ;
p15= p14+p[15]*32768 ;
p16= p15+p[16]*32768 ;
p17= p16+p[17]*32768 ;
p18= p17+p[18]*32768 ;
p19= p18+p[19]*32768 ;
p20= p19+p[20]*32768 ;
p21= p20+p[21]*32768 ;
p22= p21+p[22]*32768 ;
p23= p22+p[23]*32768 ;
p24= p23+p[24]*32768 ;
p25= p24+p[25]*32768 ;
p26= p25+p[26]*32768 ;
p27= p26+p[27]*32768 ;
p28= p27+p[28]*32768 ;
p29= p28+p[29]*32768 ;
p30= p29+p[30]*32768 ;
p31= p30+p[31]*32768 ;
p32= p31+p[32]*32768 ;
p33= p32+p[33]*32768 ;
p34= p33+p[34]*32768 ;
p35= p34+p[35]*32768 ;
p36= p35+p[36]*32768 ;
p37= p36+p[37]*32768 ;
p38= p37+p[38]*32768 ;
p39= p38+p[39]*32768 ;
// *****************************************************************
// main rendering loop:
// *****************************************************************
for ( i=0; i p0 )k= 1 ;
if(j > p1 )k= 2 ;
if(j > p2 )k= 3 ;
if(j > p3 )k= 4 ;
if(j > p4 )k= 5 ;
if(j > p5 )k= 6 ;
if(j > p6 )k= 7 ;
if(j > p7 )k= 8 ;
if(j > p8 )k= 9 ;
if(j > p9 )k= 10 ;
if(j > p10)k= 11 ;
if(j > p11)k= 12 ;
if(j > p12)k= 13 ;
if(j > p13)k= 14 ;
if(j > p14)k= 15 ;
if(j > p15)k= 16 ;
if(j > p16)k= 17 ;
if(j > p17)k= 18 ;
if(j > p18)k= 19 ;
if(j > p19)k= 20 ;
if(j > p20)k= 21 ;
if(j > p21)k= 22 ;
if(j > p22)k= 23 ;
if(j > p23)k= 24 ;
if(j > p24)k= 25 ;
if(j > p25)k= 26 ;
if(j > p26)k= 27 ;
if(j > p27)k= 28 ;
if(j > p28)k= 29 ;
if(j > p29)k= 30 ;
if(j > p30)k= 31 ;
if(j > p31)k= 32 ;
if(j > p32)k= 33 ;
if(j > p33)k= 34 ;
if(j > p34)k= 35 ;
if(j > p35)k= 36 ;
if(j > p36)k= 37 ;
if(j > p37)k= 38 ;
if(j > p38)k= 39 ;
// do the affine transform for this stroke
newx= a[k]*x + b[k]*y + e[k] ;
newy= c[k]*x + d[k]*y + f[k] ;
x= newx ;
y= newy ;
ix= (int) x + (int) 100;
iy= (int) (580. - y) ;
g.drawLine(ix,iy,ix,iy);
// if(kbhit()) break ;
}
// g.drawString(" rifs .... after dot plot ",10,320);
}
}