#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DELIM " \t\n"

char fontdata_varname[100];
char fontfamily[100];
char fontname[100];
char fontencoding[100];
char fontcharset[100];
int fontwidth;
int fontheight;
int n_char;
int n_fontboundingbox_width;
int n_fontboundingbox_height;
int n_char_count;
char *s_char_comment;

main(argc, argv)
    int argc;
    char *argv[];
{
    char s[1024];
    char *t, *t0, *t1;
    char last_bitmapline[1024];
    int n_bitmapline_count;

    init_vars(argc, argv);

    for (;;) {
	if (fgets(s, sizeof s, stdin) == NULL) break;
	t0 = strtok(s, DELIM);
//	printf("token : '%s'\n", t0);
	if (t0 == NULL) break;

	if (strcmp(t0, "FONTBOUNDINGBOX") == 0) {
	    t1 = strtok(NULL, DELIM);
	    n_fontboundingbox_width = atoi(t1);
	    t1 = strtok(NULL, DELIM);
	    n_fontboundingbox_height = atoi(t1);
	}
	else if (strcmp(t0, "CHARS") == 0) {
	    t1 = strtok(NULL, DELIM);
	    n_char = atoi(t1);
	    break;
	}
    }

    print_head();

    n_bitmapline_count = -1;
    for (;;) {
	if (fgets(s, sizeof s, stdin) == NULL) break;
	t0 = strtok(s, DELIM);
	if (t0 == NULL) break;

	if (strcmp(t0, "STARTCHAR") == 0) {
	    s_char_comment = strtok(NULL, DELIM);
	    print_startchar();
	}
	else if (strcmp(t0, "BITMAP") == 0) {
	    n_bitmapline_count = 0;
	}
	else if (strcmp(t0, "ENDCHAR") == 0) {
	    while (n_bitmapline_count++ < n_fontboundingbox_height) {
		print_bitmap_line(last_bitmapline);
	    }
	    print_endchar();
	    n_bitmapline_count = -1;
	}
	else if (n_bitmapline_count >= 0) {
//	    printf("bitmap %s\n", t0);
	    print_bitmap_line(t0);
	    strcpy(last_bitmapline, t0);
	    n_bitmapline_count++;
	}
    }

    print_tail();
}

init_vars(argc, argv)
    int argc;
    char *argv[];
{
    char fontfamily_upr[sizeof(fontfamily)];
    char fontcharset_upr[sizeof(fontcharset)];

    if (argc == 1) {
	printf("usage: %s <fontfamily> [<encoding> [<charset>]]\n");
	exit(1);
    }

    strcpy(fontfamily, (argc > 1) ? argv[1]: "<fontfamily>");
    strcpy(fontencoding, (argc > 2) ? argv[2]: "10x4x4");
    strcpy(fontcharset, (argc > 3) ? argv[3]: "hangul");

    strcpy(fontcharset_upr, fontcharset);
    strupr(fontcharset_upr);
    strcpy(fontfamily_upr, fontfamily);
    strupr(fontfamily_upr);
    sprintf(fontname, "%s%s%s", fontcharset_upr, fontencoding, fontfamily_upr);

    n_char = 0;
    n_fontboundingbox_width = 0;
    n_fontboundingbox_height = 0;
    n_char_count = 0;
    fontwidth = 16;
    fontheight = 16;

    sprintf(fontdata_varname, "fontdata_%s%s%s_%dx%d", 
	    fontcharset, fontencoding, fontfamily, fontwidth, fontheight);
}

print_head()
{
    int fontdatamax = n_char * (n_fontboundingbox_width+7)/8 * n_fontboundingbox_height;

    printf("#include <linux/config.h>\n");
    printf("#include <video/font.h>\n");
    printf("\n");
    printf("#define FONTDATAMAX %d\n", fontdatamax);
    printf("\n");
    printf("static unsigned char %s[FONTDATAMAX] = {\n", 
	    fontdata_varname);
	         
}

print_tail()
{
    printf("};\n");
    printf("\n");
    printf("struct fbcon_font_desc font_%s%s%s_%dx%d = {\n", 
	    fontcharset, fontencoding, fontfamily, fontwidth, fontheight);
    printf("        %s_%dx%d_IDX,\n", fontname, fontwidth, fontheight);
    printf("        \"%s_%dx%d\",\n", fontname, fontwidth, fontheight);
    printf("        %d,\n", fontwidth);
    printf("        %d,\n", fontheight);
    printf("        %s,\n", fontdata_varname);
    printf("        0\n");
    printf("#ifdef CONFIG_FBCON_HANGUL_OUTPUT\n");
    printf("	, \"%s\", \n", fontcharset);
    printf("	\"%s\",\n", fontencoding);
    printf("	\"%s\"\n", fontfamily);
    printf("#endif\n");
    printf("};\n");
    printf("\n");
}

print_startchar()
{
    printf("        /* %d 0x%02x %s */\n", n_char_count, n_char_count, s_char_comment);
}

print_endchar()
{
    printf("\n");
    n_char_count++;
}

print_bitmap_line(line)
char *line;
{
    int len = strlen(line);
    int i, j;
    unsigned char data;

    printf("        ");

    for (i = 0; i < len; i += 2)
    {
	printf("0x%c%c, ", line[i], line[i+1]);
    }

    printf("/* ");
    
    for (i = 0; i < len; i++) {
	if (line[i] <= '9')
	    data = line[i] - '0';
	else if (line[i] <= 'F')
	    data = line[i] - 'A' + 10;
	else
	    data = line[i] - 'a' + 10;
	for (j = 0; j < 4; j++) {
	    printf("%c", (data & 0x08) ? '1' : '0');
	    data <<= 1;
	}
    }

    printf(" */");
    printf("\n");
}

strupr(s)
    char *s;
{
    for (; *s; s++)
	*s = toupper(*s);
}
