#include "stdio.h" #include "stdlib.h" #include "termios.h" #define ei else if #define KEY_ALT 0x400000 #define KEY_UP 0x200001 #define KEY_DOWN 0x200002 #define KEY_LEFT 0x200003 #define KEY_RIGHT 0x200004 #define KEY_HOME 0x200005 #define KEY_END 0x200006 #define KEY_INS 0x200007 #define KEY_DEL 0x200008 #define KEY_PGUP 0x200009 #define KEY_PGDN 0x200010 int getkey(){ int c = getchar(); if(c == EOF)return EOF; if(c == 033){ c = getchar(); if(c == '['){ c = getchar(); if(c=='A')return KEY_UP; if(c=='B')return KEY_DOWN; if(c=='C')return KEY_RIGHT; if(c=='D')return KEY_LEFT; if(c=='1') { c = getchar(); if(c=='~')return KEY_HOME; } if(c=='2') { c = getchar(); if(c=='~')return KEY_INS; } if(c=='3') { c = getchar(); if(c=='~')return KEY_DEL; } if(c=='4') { c = getchar(); if(c=='~')return KEY_END; } if(c=='5') { c = getchar(); if(c=='~')return KEY_PGUP; } if(c=='6') { c = getchar(); if(c=='~')return KEY_PGDN; } }else if(c == 'O'){ c = getchar(); if(c=='F')return KEY_HOME; if(c=='H')return KEY_END; } return c+KEY_ALT; } return c; } unsigned oterm_get_hex(int y, char *prompt) { unsigned num = 0; while(1) { printf("\033[%d;0H\033[2K%s %x",y,prompt,num); int c = getkey(); if (c == EOF || c == '\r')break; if (c >= '0' && c <= '9')num = num * 16 + c - '0'; if (c >= 'A' && c <= 'F')num = num * 16 + c - 'A' + 10; if (c >= 'a' && c <= 'f')num = num * 16 + c - 'a' + 10; if (c == '\b')num /= 16; } return num; } struct bdfglyph { char name[16]; int encoding; int dwidth; int bbox[4]; unsigned bitmap[16]; }; struct bdfglyph *make_blank_char(unsigned gi) { struct bdfglyph *g = calloc(1,sizeof(struct bdfglyph)); g->encoding = gi; sprintf(g->name,"uni%X",gi); g->dwidth = 18; return g; } unsigned leftshft(unsigned x,int i){ if(i>0)return x << i; if(i<0)return x >> -i; return x; } int outputasbitmap(struct bdfglyph *g){ int j; for(j=0;j<4;j++){ int b; for (b=0x20000;b!=0;b/=4) { int t = (g->bitmap[j*4]&b ?0x01:0x00) | (g->bitmap[j*4]&(b/2) ?0x08:0x00) | (g->bitmap[j*4+1]&b ?0x02:0x00) | (g->bitmap[j*4+1]&(b/2)?0x10:0x00) | (g->bitmap[j*4+2]&b ?0x04:0x00) | (g->bitmap[j*4+2]&(b/2)?0x20:0x00) | (g->bitmap[j*4+3]&b ?0x40:0x00) | (g->bitmap[j*4+3]&(b/2)?0x80:0x00); printf("\342%c%c",(t>>6)|0240,(t&077)|0200); } printf("\n\r"); } } void outputbigwithcur(struct bdfglyph *g, int y, int x){ // const char *const spa = " "; const char *const blk = "██"; const char *const spacur = "\033[32m▒▒\033[0m"; const char *const blkcur = "\033[42m▒▒\033[0m"; printf("character %x\r\n",g->encoding);// encoding number not editable directly printf("name: %s",g->name); if(y == -1){printf("█");} printf("\n\r"); int j; for(j = 0;j < 16;j++) { unsigned b; int i; for (i=0,b=0x20000;b!=0;b/=2,i++) { if (i == x && j == y) { if(g->bitmap[j]&b) fputs(blkcur,stdout); else fputs(spacur,stdout); } else { if(g->bitmap[j]&b)fputs(blk,stdout); else fputs(spa,stdout); } } fputs("\n\r",stdout); } } char line[300]; int main(int argc, char **argv){ FILE *bdfin = fopen(argv[1],"r"); FILE *bdfout = fopen("out.bdf","w"); do { fgets(line,300,bdfin); if (!strncmp(line,"CHARS ",6)) break; // fputs(line,bdfout); printf("%s",line); } while(1); int nchars; sscanf(line,"CHARS %d",&nchars); //printf("allocation %d chars\n",nchars); struct bdfglyph **font = (void*)calloc(0x20000,sizeof(void*)); // BMP and SMP do { struct bdfglyph g; if(!fgets(line,300,bdfin))break; if(!strncmp(line,"ENDFONT",7))break; sscanf(line,"STARTCHAR %16s",g.name); fgets(line,300,bdfin); int ccode; sscanf(line,"ENCODING %d",&g.encoding); ccode = g.encoding; printf("status: U%05x\n",ccode); do fgets(line,300,bdfin); while(strncmp(line,"DWIDTH",6)); int dwidth; sscanf(line,"DWIDTH %d",&g.dwidth); fgets(line,300,bdfin); sscanf(line,"BBX %d %d %d %d",g.bbox,g.bbox+1,g.bbox+2,g.bbox+3); // width, height, x offset, y offset (of lower left corner) fgets(line,300,bdfin); sscanf(line,"BITMAP"); int bwidth = g.bbox[0]/8 + !!(g.bbox[0]%8); int bottom = 12 - g.bbox[3]; int top = bottom - g.bbox[1]; int lsb = g.bbox[2]; int j,i; unsigned bitmap[16]; for(j=0;j<g.bbox[1];j++){ fgets(line,300,bdfin); sscanf(line,"%x",bitmap+j); } for(j=0;j<16;j++){ g.bitmap[j]=0; if(j >= top && j < bottom) { int k = j - top; g.bitmap[j] = leftshft(bitmap[k],18 - bwidth * 8 - lsb); } } //outputasbitmap(g); font[ccode] = (struct bdfglyph*)malloc(sizeof(struct bdfglyph)); *font[ccode] = g; do fgets(line,300,bdfin); while(strncmp(line,"ENDCHAR",7)); }while(1); struct termios oldterm; struct termios rawterm; tcgetattr(0,&oldterm); cfmakeraw(&rawterm); tcsetattr(0,TCSANOW,&rawterm); /* editor state */ int gi=60;// index of glyph being edited int y=0,x=0;// cursor position int redraw = 1; while (1) { if(gi >= 0x20000)gi = 0x1FFFF; struct bdfglyph *g = font[gi]; if(redraw){ printf("\033[2J\033[HBDF EDIT [^Q exit] [^G go to]\r\n"); if (g) { outputasbitmap(g); outputbigwithcur(g,y,x); } else { printf ("no character U%x\n\r",gi); printf ("(^A to add blank)"); } } redraw = 1; int c = getkey(); if (c == CTRL('Q'))break; // quit ei (c == CTRL('G'))gi = oterm_get_hex(2,"go to char:"); ei (c == CTRL('A') && !g)font[gi] = make_blank_char(gi); ei (c == KEY_UP && y > 0)y--; ei (c == KEY_DOWN && y < 15)y++; ei (c == KEY_LEFT && x > 0)x--; ei (c == KEY_RIGHT && x < 17)x++; ei (c == KEY_PGUP && gi > 0)gi--; ei (c == KEY_PGDN && gi < 0x1FFFF)gi++; ei (c == KEY_HOME) { if (gi > 0)gi--; while(gi > 0 && !font[gi])gi--; } ei (c == KEY_END) { if (gi < 0x1FFFF)gi++; while (gi < 0x1FFFF && !font[gi])gi++; } ei (c == 'd' && g)g->bitmap[y] |= (0x20000 >> x); ei (c == 'e' && g)g->bitmap[y] &= ~(0x20000 >> x); ei (c == ' ' && g)g->bitmap[y] ^= (0x20000 >> x); else redraw = 0; } tcsetattr(0,TCSANOW,&oldterm); /* now, output edited font */ unsigned charcount = 0; //count the characters in font for (gi = 0; gi < 0x20000; gi++) { if(font[gi])charcount++; } fprintf(bdfout,"STARTFONT 2.1\n"); fprintf(bdfout,"FONT neoletters\n"); fprintf(bdfout,"SIZE 12 75 75\n"); fprintf(bdfout,"FONTBOUNDINGBOX 18 16 0 -4\n"); fprintf(bdfout,"STARTPROPERTIES 3\n"); fprintf(bdfout,"PIXEL_SIZE 16\n"); fprintf(bdfout,"FONT_ASCENT 12\n"); fprintf(bdfout,"FONT_DESCENT 4\n"); fprintf(bdfout,"ENDPROPERTIES\n"); fprintf(bdfout,"CHARS %d\n",nchars); for (gi = 0; gi < 0x20000; gi++) { struct bdfglyph *g = font[gi]; if(!g)continue; fprintf(bdfout,"STARTCHAR %s\n",g->name); fprintf(bdfout,"ENCODING %d\n",gi); fprintf(bdfout,"SWIDTH %d 0\n",g->dwidth*500/8); fprintf(bdfout,"DWIDTH %d 0\n",g->dwidth); /*calculate bounding box*/ int j; unsigned orsum=0; int topnonzero = -1; int botnonzero = -1; for(j=0;j<16;j++){ orsum |= g->bitmap[j]; if(topnonzero == -1 && g->bitmap[j] != 0) topnonzero = j; if(g->bitmap[j] != 0) botnonzero = j; } int height = botnonzero - topnonzero + 1; int yoff = 11 - botnonzero; if (botnonzero == -1)yoff = 0; int i; int lefnonzero = -1; int rignonzero = -1; for(i=0;i<18;i++){ int p = !!((0x20000>>i)&orsum); if(p) rignonzero = i; if(p && lefnonzero == -1) lefnonzero = i; } int width = rignonzero - lefnonzero + 1; int xoff = lefnonzero; if(lefnonzero == -1)xoff = 0; int bytes = width%8 ? width/8+1 : width/8; int zershift = 17-rignonzero; int byteshift = bytes*8-width; fprintf(bdfout,"BBX %d %d %d %d\nBITMAP\n",width,height,xoff,yoff); for(j=topnonzero;j<=botnonzero;j++){ fprintf(bdfout,"%0*X\n",bytes*2,(g->bitmap[j]>>zershift)<<byteshift); } fprintf(bdfout,"ENDCHAR\n"); } fprintf(bdfout,"ENDFONT\n"); }