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