/*
   bdf2bfb.c ver 1.0.0
   Copyright (C) 2000 Tomohide Naniwa. All rights reserved.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   Last modified: Feb. 2, 2000.
*/
#include <stdio.h>

#define FH_MEMO_SIZE            512

struct font_header {
  char magic[4];
  short fnt_size;   /* bytes per one character bit patern */
  short fnt_height; /* font height */
  short fnt_width;   /* font width */
  unsigned short top_code;
  unsigned short end_code;
  char unused[498];  /* empty */
  char memo[FH_MEMO_SIZE];
} fheader;

#define MAGIC "BFB"

char *heading[] = {
  "FONTBOUNDINGBOX ",
  "CHARS ",
  "ENCODING ",
  "BITMAP",
  "ENDCHAR"};

int cal_offset(code)
     int code;
{
  int k1, k2;
  if (code > 256) {
    k2 = code & 0xFF;
    k1 = (code >> 8) & 0xFF;
    if (k1 < 0x29) {
      return((k1 - 0x21)*94 + k2-0x21);
    }
    else {
      return((k1 - 0x30)*94 + k2-0x21) + 752;
    }
  }
  else {
    return(code);
  }
}

int inv(c)
     int c;
{
  int i, v = 0;

  for(i = 0; i < 8; ++i) {
    v <<= 1;
    v += c & (0x01);
    c >>= 1;
  }
  return(v);
}

main(argc, argv)
     int argc;
     char *argv[];
{
  FILE *fp, *fo;
  char line[256];
  int w, h, max_c = 0, min_c = 0x0FFFF;
  int len, num, code, fsize, offset;
  int i, j, c, cnt;

  if (argc < 3) {
    printf("usage: %s input output\n", argv[0]);
    exit(-1);
  }
  if ((fp = fopen(argv[1], "r")) == NULL) {
    perror("cant open file for input");
    exit(-1);
  }
  if ((fo = fopen(argv[2], "w")) == NULL) {
    perror("cant open file for output");
    exit(-1);
  }
  i = 0;
  len = strlen(heading[i]);
  while(fgets(line, 256, fp) != NULL) {
    if (strncasecmp(heading[i], line, len) == 0) {
      switch(i) {
      case 0:
	sscanf(&line[len], "%d%d", &w, &h);
	fsize = ((w / 8) + ((w % 8) != 0))*h;
	printf("width = %d height = %d fsize = %d\n", w, h, fsize);
	len = strlen(heading[++i]);
	break;
      case 1:
	sscanf(&line[len], "%d", &num);
	printf("font number %d\n", num);
	len = strlen(heading[++i]);
	break;
      }
      if (i == 2) break; 
    }
  }
  fseek(fo, 1024, SEEK_SET);
  for(cnt = 0; cnt < num; ++cnt) {
      while(fgets(line, 256, fp) != NULL) {
	if (strncasecmp(heading[i], line, len) == 0) break;
      }
      sscanf(&line[len], "%d", &code);
      len = strlen(heading[++i]);
      offset = cal_offset(code);
      if (max_c < code) max_c = code;
      if (min_c > code) min_c = code;

      while(fgets(line, 256, fp) != NULL) {
	if (strncasecmp(heading[i], line, len) == 0) break;
      }
      len = strlen(heading[++i]);
      for(j = 0; j < fsize; ++j) {
	fscanf(fp, "%2x", &c);
	line[j] = (char) (inv(c) & 0xFF);
      }
      fseek(fo, 1024+offset*fsize, SEEK_SET);
      fwrite(line, 1, fsize, fo);
      while(fgets(line, 256, fp) != NULL) {
	if (strncasecmp(heading[i], line, len) == 0) break;
      }
      i = 2;
      len = strlen(heading[i]);
  }

  strcpy(fheader.magic, MAGIC);
  fheader.fnt_size = fsize;
  fheader.fnt_height = h;
  fheader.fnt_width = w;
  fheader.top_code = min_c;
  fheader.end_code = max_c;
  fseek(fo, 0, SEEK_SET);
  fheader.memo[0] = 0;
  len = 0;
  printf("Please input memo\n");
  while(1) {
    fgets(line, 255, stdin);
    if (line[0] == '.') break;
    strcat(&fheader.memo[len], line);
    len += strlen(line)+1;
  }
  fwrite(&fheader, 1, sizeof(struct font_header), fo);
  fclose(fp);
  fclose(fo);
}
