headerphoto

What follows is a simple Java program to create a header from a specific font. The header consists of an array of numbers, each number being a set of bits representing the bits that are set in a column.

 

 

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.PrintWriter;

import javax.imageio.ImageIO;


/** Give the statics at the top of this class, create a header file for
 * drawing a font */
public class FontHeaderMaker {
    // -----------------------------------------------------------------------
    static int HEIGHT = 12; // max height is 32 (that's all we can fit in a std int)
    static int CHARS = 128;    
    static String FONT_NAME = "Sans";
    // -----------------------------------------------------------------------
    static int MAXWIDTH = HEIGHT*CHARS; // assume square
    
    static int formatCol = 0; // for formattedPrint
    public static void formattedPrintReset() {
        formatCol = 0;
    }
    public static void formattedPrint(PrintWriter pw, String str) {
        if (formatCol + str.length() > 78) {
          formatCol = 0;
          pw.println();
        }
        formatCol+=str.length();
        pw.print(str);
    }
    
    public static void main(String[] args) throws Exception {
        
        BufferedImage im = new BufferedImage(MAXWIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        Graphics g = im.getGraphics();
        int fontsize = 2;
        do {
            g.setFont(new Font(FONT_NAME,0,++fontsize));
        } while (g.getFontMetrics().getHeight()<HEIGHT);
        FontMetrics metrics = g.getFontMetrics();
        // clear background
        g.setColor(Color.BLACK);
        g.fillRect(0,0,MAXWIDTH,HEIGHT);
        // draw fonts + work out widths
        int widths[] = new int[CHARS];
        g.setColor(Color.WHITE);
        int x = 0;
        for (int ch = 0; ch<CHARS; ch++) {
            if (ch>=32) // <32 are control chars, 32 is space
                widths[ch] = metrics.charWidth((char)ch);
            if (widths[ch] > 0)
              g.drawString(""+(char)ch, x, metrics.getHeight()-metrics.getDescent());
            x += widths[ch];
        }
        // output image so people can see
        ImageIO.write(im, "png", new File("font"+HEIGHT+"_sample.png"));
        // get image data
        int rgb[] = new int[x*HEIGHT];
        im.getRGB(0, 0, x, HEIGHT, rgb, 0, x);        
        // create the header 
        PrintWriter header = new PrintWriter(new File("font"+HEIGHT+".h"));
        header.println("// Auto-generated header, created by FontHeaderMaker");
        header.println("// Gordon Williams, http://www.pur3.co.uk");
        header.println("");
        header.println("unsigned char FONT"+HEIGHT+"_WIDTH["+CHARS+"] = {");
        formattedPrintReset();
        for (int i=0;i<CHARS;i++) {
            String str = widths[i]+",";
            formattedPrint(header, str);
        }            
        header.println("};");
        header.println();
        header.println("unsigned short FONT"+HEIGHT+"_OFFSET["+CHARS+"] = {");
        formattedPrintReset();
        int offset = 0;
        for (int i=0;i<CHARS;i++) {
            String str = offset+",";
            formattedPrint(header, str);
            offset += widths[i];
        }            
        header.println("};");
        header.println();
        
        String dataType;
        if (HEIGHT<=8)
            dataType = "char";
        else if (HEIGHT<=16)
            dataType = "short";
        else
            dataType = "int";
        
        header.println("unsigned "+dataType+" FONT"+HEIGHT+"_DATA["+x+"] = {");
        formattedPrintReset();
        for (int i=0;i<x;i++) {
            int hex = 0;
            for (int y=0;y<HEIGHT;y++) {
                if ((rgb[i+(y*x)]&0xFF) > 127)
                    hex |= 1;
                hex = hex << 1;
            }
            String str;
            
            if (hex>0)
                str = "0x"+Integer.toHexString(hex)+",";
            else
                str = hex+",";
            formattedPrint(header, str);
        }            
        header.println("};");
        
        
        header.close();
    }
}


 

 

 

The finished file looks a bit like this:

 

// Auto-generated header, created by FontHeaderMaker
// Gordon Williams, http://www.pur3.co.uk

unsigned char FONT12_WIDTH[128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,4,5,8,6,10,
9,3,4,4,5,8,3,4,3,3,6,6,6,6,6,6,6,6,6,6,3,3,8,8,8,5,11,7,7,8,8,7,6,8,8,3,3,7,
6,9,8,8,7,8,7,7,5,8,7,9,6,7,6,4,3,4,8,5,5,6,6,5,6,6,4,6,6,2,2,5,2,10,6,6,6,6,
4,5,4,6,6,8,6,6,5,6,3,6,8,6,};

unsigned short FONT12_OFFSET[128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,7,12,20,
26,36,45,48,52,56,61,69,72,76,79,82,88,94,100,106,112,118,124,130,136,142,145,
148,156,164,172,177,188,195,202,210,218,225,231,239,247,250,253,260,266,275,
283,291,298,306,313,320,325,333,340,349,355,362,368,372,375,379,387,392,397,
403,409,414,420,426,430,436,442,444,446,451,453,463,469,475,481,487,491,496,
500,506,512,520,526,532,537,543,546,552,560,};

unsigned short FONT12_DATA[566] = {
0,0,0,0,0,0x7d0,0,0,0x700,0,0x700,0,0,0x40,0x170,0x7c0,0x140,0x1f0,0x740,
0x100,0,0x190,0x290,0x7f8,0x250,0x260,0,0x780,0x480,0x7b0,0xc0,0x180,0x6f0,
0x90,0xf0,0,0,0xe0,0x330,0x490,0x490,0x260,0x20,0xd0,0,0,0x700,0,0,0x7f0,
0x808,0,0,0xc18,0x3e0,0,0x480,0x300,0x780,0x300,0x480,0,0x80,0x80,0x80,0x7f0,
0x80,0x80,0x80,0,0x18,0,0,0x40,0x40,0x40,0,0x10,0,0x18,0x1e0,0x600,0,0x3e0,
0x410,0x410,0x410,0x3e0,0,0x410,0x410,0x7f0,0x10,0x10,0,0x210,0x430,0x450,
0x490,0x310,0,0x220,0x490,0x490,0x490,0x360,0,0xc0,0x140,0x640,0x7f0,0x40,0,
0x710,0x510,0x510,0x510,0xe0,0,0x3e0,0x690,0x490,0x490,0x460,0,0x400,0x410,
0x460,0x580,0x600,0,0x360,0x490,0x490,0x490,0x360,0,0x310,0x490,0x490,0x4b0,
0x3e0,0,0x110,0,0,0x118,0,0,0x80,0x80,0x140,0x140,0x140,0x220,0,0,0x140,0x140,
0x140,0x140,0x140,0x140,0,0,0x220,0x140,0x140,0x140,0x80,0x80,0,0,0x400,0x4d0,
0x500,0x600,0,0x1f0,0x318,0x60c,0x4e4,0x4a4,0x4e4,0x428,0x260,0x1c0,0,0x10,
0xe0,0x340,0x440,0x340,0xe0,0x10,0,0x7f0,0x490,0x490,0x490,0x360,0,0,0x1c0,
0x220,0x410,0x410,0x410,0x220,0,0,0x7f0,0x410,0x410,0x410,0x630,0x3e0,0,0,
0x7f0,0x490,0x490,0x490,0x490,0,0,0x7f0,0x480,0x480,0x480,0,0,0x3e0,0x630,
0x410,0x490,0x490,0x2e0,0,0,0x7f0,0x80,0x80,0x80,0x80,0x7f0,0,0,0x7f0,0x4,0x4,
0x7f8,0,0,0x7f0,0x80,0x140,0x220,0x410,0,0,0x7f0,0x10,0x10,0x10,0x10,0,0x7f0,
0x300,0xc0,0x20,0xc0,0x300,0x7f0,0,0,0x7f0,0x200,0x180,0x40,0x20,0x7f0,0,0,
0x3e0,0x630,0x410,0x410,0x630,0x3e0,0,0,0x7f0,0x480,0x480,0x480,0x300,0,0,
0x3e0,0x630,0x410,0x410,0x628,0x3c0,0,0,0x7f0,0x480,0x480,0x4c0,0x320,0x10,0,
0x320,0x490,0x490,0x490,0x260,0,0x400,0x400,0x7f0,0x400,0x400,0,0x7e0,0x10,
0x10,0x10,0x10,0x7e0,0,0x600,0x180,0x60,0x10,0x60,0x180,0x600,0x600,0x1c0,
0x30,0x1c0,0x600,0x1c0,0x30,0x1c0,0x600,0x410,0x630,0x1c0,0x1c0,0x630,0x410,
0x400,0x200,0x100,0xf0,0x100,0x200,0x400,0x410,0x430,0x4d0,0x590,0x610,0x410,
0,0xff8,0x808,0,0x600,0x1e0,0x18,0,0x808,0xff8,0,0,0x100,0x200,0x400,0x400,
0x200,0x100,0,0x4,0x4,0x4,0x4,0x4,0,0x800,0x400,0,0,0,0x30,0x150,0x150,0x150,
0xf0,0,0xff0,0x110,0x110,0x110,0xe0,0,0xe0,0x110,0x110,0x110,0,0xe0,0x110,
0x110,0x110,0xff0,0,0xe0,0x150,0x150,0x150,0xd0,0,0x100,0xff0,0x900,0x800,
0xe0,0x114,0x114,0x114,0x1f8,0,0xff0,0x100,0x100,0x100,0xf0,0,0x9f0,0x4,0x9fc,
0,0xff0,0x40,0xa0,0x110,0,0xff0,0,0x1f0,0x100,0x100,0x100,0xf0,0x100,0x100,
0x100,0xf0,0,0x1f0,0x100,0x100,0x100,0xf0,0,0xe0,0x110,0x110,0x110,0xe0,0,
0x1fc,0x110,0x110,0x110,0xe0,0,0xe0,0x110,0x110,0x110,0x1fc,0,0x1f0,0x100,
0x100,0,0x190,0x150,0x150,0x170,0x100,0x7f0,0x110,0x110,0,0x1e0,0x10,0x10,
0x10,0x1f0,0,0x180,0x60,0x10,0x60,0x180,0,0x1c0,0x30,0xc0,0x100,0xc0,0x30,
0x1c0,0,0x110,0xa0,0x40,0xa0,0x110,0,0x184,0x64,0x18,0x60,0x180,0,0x110,0x130,
0x150,0x190,0,0x80,0x80,0xf78,0x808,0,0,0xffc,0,0,0x808,0xf78,0x80,0x80,0,0,0,
0x80,0x80,0x40,0x40,0x80,0,0,0x7fc,0x404,0x404,0x404,0x7fc,};