We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › create font with rect()
Pages: 1 2 
create font with rect() (Read 1244 times)
create font with rect()
Oct 9th, 2007, 10:53am
 
Hi,

I'm just starting a new project and actually I'm just stuck with the algorithm (should i go with path finding or ??). I'm working on a sketch that can create some kind of minimal fonts using only squares (rect()).

What i'd like is that my sketch can be feed with a string buffer (either from a file or from keybard input) and then trace the corresponding letter dynamically.

Any ideas ?

Re: create font with rect()
Reply #1 - Oct 9th, 2007, 12:23pm
 
is that gonna be a monospaced font?

then it's easier, say for 7x6 bits the letter "1" would be:

int bits[] = new int[] {
0,0,0,1,0,0,0,
0,0,1,1,0,0,0,
0,1,0,1,0,0,0,
0,0,0,1,0,0,0,
0,0,0,1,0,0,0,
0,0,1,1,1,0,0
};

when drawing this, skip the 0s and step into a new row after every 7th element

now you could map char-codes to one of those bit-letters and then just loop thru the given string to draw:

String abc = "My Stzring ABC";

for ( int i = 0; i<abc.length(); i++ )
{
   println( abc.charAt(i) ); // char value
   println( (int)abc.charAt(i) ); // int value
}

F
Re: create font with rect()
Reply #2 - Oct 9th, 2007, 12:38pm
 
(Edit: oups, fjen answered before I did!)

Hi. I'm not sure what you want to do :

1) use an existing font as a model to draw squares (something a bit like a mosaic effect)

or

2) draw a combination of squares when you get a keyboard (or file) input, each letter corresponding to a special combination (something like a custom font)

For 'custom font' option, it seems like you'll have to map each character with a mask (say an array of 4x4 booleans), in an associative array. Once you have an input, you draw the squares corresponding to the input character's mask.
Re: create font with rect()
Reply #3 - Oct 9th, 2007, 1:23pm
 
Thanks for the answers, very usefull.
I don't think it's monospace, but not sure.

You can find an example of a static creation, here:

http://img511.imageshack.us/img511/3654/screenip2.png

Niko, it's the guess number 2 :]
I'll give a try and let you know

Re: create font with rect()
Reply #4 - Oct 9th, 2007, 1:54pm
 
then try something like this:

Code:


// fjenett 20071009


int[] letter1 = new int[] {
0,0,1,0,0,
0,1,1,0,0,
1,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,1,1,1,0
};

HashMap bitfonts = new HashMap();

bitfonts.put( "1", letter1 );


String abc = "1";

for ( int i = 0; i<abc.length(); i++ )
{
String cKey = abc.charAt(i)+"";
int[] letter = (int[])(bitfonts.get( cKey ));
int lx, ly;
for ( int k = 0 ; k < letter.length; k++ )
{
lx = k % 5; ly = k / 5;
if ( letter[k] == 0 ) continue;

rect( lx*5, ly*5, 5, 5 );
}
}


F
Re: create font with rect()
Reply #5 - Oct 9th, 2007, 4:56pm
 
Thx a lot fjen, you help me so much !!

I didn't deal with java classes yet but found some informations about hashmap on the www.

Btw, i just wonder if i create a structure for each letters, will they be stored in memory at startup ? I mean is there a way to only load in memory the letter that should be displayed ? (maybe it's the goal of the hashtable

And is there a way to access them into a separate tabs ? I tried it, but seems the main sketch can't see them. Never deal with data on another tab yet, only classes.

Sorry, a little bit lost with that new areas (for me), but very exciting.

Regards.
Re: create font with rect()
Reply #6 - Oct 9th, 2007, 5:30pm
 
Code:

// fjenett 20071009

void setup () {
size( 200, 200 );
initBitFonts();
}

void draw () {
drawText( "1a", 20, 20 );
}

// everything below can go into another tab ..

HashMap bitfonts;

void initBitFonts() {
bitfonts = new HashMap();
bitfonts.put(
"1", new int[] {
0,0,1,0,0,
0,1,1,0,0,
1,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
1,1,1,1,1
});
bitfonts.put(
"a", new int[] {
0,1,1,1,0,
0,0,0,0,1,
0,1,1,1,1,
1,0,0,0,1,
1,0,0,0,1,
0,1,1,1,1
});
}

void drawText ( String txt, int x, int y )
{
int rectSize = 5;
int letterW = 5;

int letterSize = letterW * rectSize + letterW;

for ( int i = 0; i<txt.length(); i++ )
{
String cKey = txt.charAt(i)+"";

int[] letter = (int[])(bitfonts.get( cKey ));
int lx, ly;
int offset = i*letterSize;

for ( int k = 0 ; k < letter.length; k++ )
{
lx = k % 5; ly = k / 5;
if ( letter[k] == 0 ) continue;

rect( x + offset + lx*5, y + ly*5, 5, 5 );
}
}
}


F
Re: create font with rect()
Reply #7 - Oct 9th, 2007, 5:32pm
 
tabs (as long as they are non-.java tabs) are just appended to one long text before processing handles (runs) them .. so there's not much to take care about. it's just the same as having everything in one tab ..
Re: create font with rect()
Reply #8 - Oct 9th, 2007, 5:41pm
 
anachronik,

> you don't have to care about the question of memory since 1) java's garbage collector does it at your place and 2) imagine you need 26 letters (a-z) + 10 numbers (0-9), you'll have to allow 6x6 int* (1 byte) each, that is : 36x36 = less than 2000 bytes = less than 2kb!!

(* you can use booleans too if you only need 0/1, it'll take less memory)

> to put them in a separate tab, declare your hashmap at the top of your main tab, before the setup() function, so it will be accessible in all your inner methods :
Code:
HashMap bitfonts = new HashMap(); 


and create a new tab containing a method to fill your hashmap, say :
Code:

initLetters() {
bitfonts.put("1", new array{...});
bitfonts.put("2", new array{...});
...
}

you'll just have to call initLetters() in your setup() to initialize the hashmap.
Re: create font with rect()
Reply #9 - Oct 9th, 2007, 9:08pm
 
Big thx thx thx to both of you !!!
Got it right now :] i've learn so much today thx again
Re: create font with rect()
Reply #10 - Oct 9th, 2007, 10:24pm
 
For these purposes it is probably inconsequential, but it is worth knowing that a boolean actually takes up a full byte because of the way it is implemented in Java: http://forum.java.sun.com/thread.jspa?threadID=405386&messageID=1775642

If you really need to save space by using booleans, you could use a byte and pack it appropriately, using bitwise operations to extract individual bits.  But if you're not severely memory-bound, you're always best off using the most logically appropriate data type; for something that's either on or off, use a boolean, for something that needs "shades of gray" either use a float or an integer, and for something that needs much higher resolution, double or long will do the trick.
Re: create font with rect()
Reply #11 - Oct 10th, 2007, 3:44am
 
Nice to know that ewjordan.
I've make some work over this sketch.
Actually i just want the space between each letter to be only one square length(=rectSize).

I guess as my letters are 5x5 I've to find each letter width in order to have the same space between each letter.That where i'm stuck actually, i've try to figure it out without sucess but i'm not far i guess.

Here's the code:

Quote:


// thx to fjen and nokoony

void setup () {
 size( 300, 50 );
 background(255);
 noStroke();
 fill(0);
 initBitFonts();
 
 //guidelines
 for (  int i=0; i < width; i++){
   stroke(0, 80);
   //line( i*4, 0, height, i*4); //nice background
   line(i*5, 0, i*5, height);
 }
 line(0, height/2, width, height/2);
 noLoop();
}

void draw () {
 drawText( "mai", 20, height/4 );
}

void drawText ( String txt, int x, int y )
{
 float rectSize = 5.0;
 float letterW = 0.0;
 float offset = 0.0;
 int[] rowSize = {0,0,0,0,0};
 
 //have to tweak it, according to the letter
 //float letterSize = letterW * rectSize  + letterW;

 //loop for handling each string character.
 for ( int i = 0; i<txt.length(); i++ )  
 {
  println(i);
   String cKey = txt.charAt(i)+"";
   int[] letter = (int[])(bitfont1.get( cKey ));  //get the current character
   float lx, ly;

   //define the width of a letter according to the max numbers of 1 in a row.
   for ( int j = 0; j < 5; j++ ) {
     for (int l =0; l < 5; l++){
       if (letter[5*j + l] ==1){
         rowSize[j]++;
       }        
     }
   }
   //assign the width of the bitfont letter
   // for exemple m = 5 (1,1,1,1,1) n = 3 (0,1,1,1,0) i = 1 (0,0,1,0,0)
   //see the letters tab.
   
   //pb seems to be there or during the previous loop
   letterW = max(rowSize);
   println(letterW);// display correct value for each cycles but sums them
   // for exemple, the word "mai" should display 5,3,1
   //and it display 5,8,9 like letterW never go back to 0
   //tried to initialize it at the start of the loop but do not work.
   
   //letterW*rectSize = width of the letter
   //just add a rectSize a space like a blank square between each letter.
   offset = i*((letterW*rectSize)+rectSize);
   
   //loop for handling each matrix value
   //trace the shape of the font
   for ( int k = 0 ; k < letter.length; k++ )  
   {  
     lx = k % 5;
     ly = k / 5;  
     if ( letter[k] == 0 ) continue;    
     rect( x + offset + lx*rectSize, y + ly*rectSize, rectSize, rectSize );
   }
 }
}




and the letters tab:

HashMap bitfont1;

void initBitFonts() {
 bitfont1 = new HashMap();
 bitfont1.put("a", new int[]{
   1, 1, 1, 0, 0,
   1, 0, 1, 0, 0,
   1, 1, 1, 0, 0,
   1, 0, 1, 0, 0,
   1, 0, 1, 0, 0        
 }
 );

 bitfont1.put("i", new int[]{
   0, 0, 1, 0, 0,
   0, 0, 1, 0, 0,
   0, 0, 1, 0, 0,
   0, 0, 1, 0, 0,
   0, 0, 1, 0, 0      
 }
 );

 bitfont1.put("m", new int[]{
   1, 1, 1, 1, 1,
   1, 0, 1, 0, 1,
   1, 0, 1, 0, 1,
   1, 0, 1, 0, 1,
   1, 0, 1, 0, 1        
 }
 );
}

Am i on the good way or totally wrong ?
Re: create font with rect()
Reply #12 - Oct 10th, 2007, 8:01am
 
> to solve your first problem, move this line (#29): int[] rowSize = {0,0,0,0,0};

just before this one (#43): for ( int j = 0; j < 5; j++ ) {

so rowSize is set back to 0 before each loop.

> but doing this this way, you'll have a problem if you consider this kind of letter 'Y':

Code:
10001
01010
00100
00100
00100

the max width is 5 (line 10001) but your algorithm will give 2.

since your font is not monospaced, it's a bit more difficult (that is why fjen asked you at the top of the topic). maybe you should 'manually' specify the width of each character in another array, or better, create an object for each letter, containing 1) the int[] array mask and 2) an integer specifying the width:

Code:
class Letter {
int[] mask;
int width;
Letter(int[] mask, int width) {
this.mask = mask;
this.width = width;
}
}
Re: create font with rect()
Reply #13 - Oct 10th, 2007, 12:48pm
 
Thx niko !

Helpful again.

Oh yes i didn't though about letters like Y or X what a shame...i'll rework my letter class the way you show me, seems pretty correct way to handle that Smiley
Re: create font with rect()
Reply #14 - Oct 10th, 2007, 2:15pm
 
I went up with something like this. have a look if you're stuck Wink

Code:
void setup () {
size( 300, 50 );
background(255);
noStroke();
fill(0);
initBitFonts();

//guidelines
for ( int i=0; i < width; i++){
stroke(0, 80);
//line( i*4, 0, height, i*4); //nice background
line(i*5, 0, i*5, height);
}
line(0, height/2, width, height/2);
noLoop();
}

void draw () {
drawText( "ami", 20, height/4 );
}

void drawText ( String txt, int x, int y ) {
int rectSize = 5;

//loop for handling each string character.
for (int i = 0; i<txt.length(); i++) {
String cKey = txt.charAt(i)+"";
Letter lt = (Letter)(bitfont1.get(cKey)); //get the current character

//loop for handling each matrix value
//trace the shape of the font
for (int k = 0 ; k < lt.mask.length; k++) {
int lx = k % 5;
int ly = k / 5;
if (lt.mask[k] == 0) continue;
rect( x + lx*rectSize, y + ly*rectSize, rectSize, rectSize );
}
// x is incremented with the letter width (lt.width) and a gap (+1) before tracing the next letter
x += (lt.width + 1)*rectSize;
}
}

HashMap bitfont1;

void initBitFonts() {
bitfont1 = new HashMap();
bitfont1.put("a", new Letter(new int[]{
1, 1, 1, 0, 0,
1, 0, 1, 0, 0,
1, 1, 1, 0, 0,
1, 0, 1, 0, 0,
1, 0, 1, 0, 0
}, 3));


bitfont1.put("i", new Letter(new int[]{
1, 0, 0, 0, 0,
1, 0, 0, 0, 0,
1, 0, 0, 0, 0,
1, 0, 0, 0, 0,
1, 0, 0, 0, 0
}, 1));

bitfont1.put("m", new Letter(new int[]{
1, 1, 1, 1, 1,
1, 0, 1, 0, 1,
1, 0, 1, 0, 1,
1, 0, 1, 0, 1,
1, 0, 1, 0, 1
}, 5));
}

class Letter {
int[] mask;
int width;
Letter(int[] mask, int width) {
this.mask = mask;
this.width = width;
}
}
Pages: 1 2