/* * bdf2bmp -- output all glyphs in a bdf-font to a bmp-image-file * version: 0.6 * date: Wed Jan 10 23:59:03 2001 * author: ITOU Hiroki (itouh@lycos.ne.jp) */ /* * Copyright (c) 2000,2001 ITOU Hiroki * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* modify if you want; color of spacing */ #define COLOR_SPACING_RED 0x9a #define COLOR_SPACING_GREEN 0x9a #define COLOR_SPACING_BLUE 0xbd /* modify if you want; out-of-dwidth over baseline */ #define COLOR_OVERBL_RED 0xca #define COLOR_OVERBL_GREEN 0xca #define COLOR_OVERBL_BLUE 0xd8 /* modify if you want; out-of-dwidth under baseline */ #define COLOR_UNDERBL_RED 0xde #define COLOR_UNDERBL_GREEN 0xde #define COLOR_UNDERBL_BLUE 0xe7 #define VERBOSE #include /* printf(), fopen(), fwrite() */ #include /* malloc(), EXIT_SUCCESS, strtol(), exit() */ #include /* strcmp(), strcpy() */ #include /* strtol() */ #include /* stat() */ #include /* stat ? */ #include /* isdigit() */ #include /* int types */ #define LINE_CHARMAX 1000 /* number of max characters in bdf-font-file; number is without reason */ #define FILENAME_CHARMAX 256 /* number of max characters in filenames; number is without reason */ #define ON 1 /* number is without reason; only needs the difference to OFF */ #define OFF 0 /* number is without reason; only needs the difference to ON */ #define PARAM_MAX 10 /* max number of parameters */ #ifdef DEBUG #define d_printf(message,arg) printf(message,arg) #else /* not DEBUG */ #define d_printf(message,arg) #endif /* DEBUG */ #ifdef VERBOSE #define v_printf(message,arg) printf(message,arg) #else /* not VERBOSE */ #define v_printf(message,arg) #endif /* VERBOSE */ /* macro */ #define STOREBITMAP() if(flagBitmap == ON){\ memcpy(nextP, sP, length);\ nextP += length;\ } struct boundingbox{ int w; /* width (pixel) */ int h; /* height */ int offx; /* offset y (pixel) */ int offy; /* offset y */ }; /* global var */ struct boundingbox font; /* global boundingbox */ static int chars; /* total number of glyphs in a bdf file */ static int dwflag = ON; /* device width; only used for proportional-fonts */ static int endian; /* 0 = MSB, 1 = LSB */ /* func prototype */ void checkEndian(void); void dwrite(const void *ptrP, int n, FILE *outP); void writeBmpFile(unsigned char *bitmapP, int spacing, int colchar, FILE *bmpP); void assignBitmap(unsigned char *bitmapP, char *glyphP, int sizeglyphP, struct boundingbox glyph, int dw); int getfontline(char* lineP, int max, FILE* inputP); unsigned char *readBdfFile(unsigned char *bitmapP, FILE *readP); void printhelp(void); int main(int argc, char *argv[]); /* * Is your-CPU-byte-order MSB or LSB? * MSB .. Most Significant Byte first (BigEndian) e.g. PowerPC, SPARC * LSB .. Least Significant Byte first (LittleEndian) e.g. Intel Pentium */ void checkEndian(void){ uint32_t uint32 = 0x12345678; unsigned char *ucharP; ucharP = (unsigned char *)(&uint32); if(*ucharP == 0x78){ d_printf("LSB 0x%x\n", *ucharP); endian = 1; }else{ d_printf("MSB 0x%x\n", *ucharP); endian = 0; } } /* * write to disk; with arranging LSBfirst(LittleEndian) byte order, * because BMP-file is defined as LSB-first */ void dwrite(const void *varP, int n, FILE *outP){ const unsigned char *p = varP; int i; unsigned char tmp; if(endian == 1){ /* LSB; write without arranging */ for(i=0; i=0; i--){ tmp = fwrite(p+i, 1, sizeof(unsigned char), outP); if(tmp != sizeof(unsigned char)){ printf("error: cannot write an output-file\n"); exit(EXIT_FAILURE); } } } } /* * 3. read bitmapAREA(onMemory) and write bmpFile with adding spacing * BMP-file: noCompression(BI_RGB), 8bitColor, Windows-Win32 type */ void writeBmpFile(unsigned char *bitmapP, int spacing, int colchar, FILE *bmpP){ long bmpw; /* bmp-image width (pixel) */ long bmph; /* bmp-image height (pixel) */ int bmppad; /* number of padding pixels */ unsigned long bmpTotalSize; /* bmp filesize (byte) */ /* bmp-lines needs to be long alined and padded with 0 */ uint32_t uint32; uint16_t uint16; int32_t sint32; unsigned char uchar; int i,x,y,g,tmp; int rowchar; /* number of row glyphs */ int bx, by; /* bmp-image width */ bmpw = (font.w+spacing)*colchar + spacing; /* bmp-image height */ rowchar = (chars/colchar) + (chars%colchar!=0); bmph = (font.h+spacing)*rowchar + spacing; v_printf(" BMP width = %d pixels\n", (int)bmpw); v_printf(" BMP height = %d pixels\n", (int)bmph); d_printf(" number of glyphs column=%d ", colchar); d_printf("row=%d\n", rowchar); bmppad = ((bmpw + 3) / 4 * 4) - bmpw; bmpTotalSize = (bmpw + bmppad) * bmph + sizeof(int32_t)*11 + sizeof(int16_t)*5 + sizeof(char)*4*256; v_printf(" BMP filesize = %d bytes\n", (int)bmpTotalSize); /* * BITMAPFILEHEADER struct */ uint16 = 0x4d42; /* 4d = 'M', 42 = 'B' */ dwrite(&uint16, sizeof(uint16), bmpP); uint32 = bmpTotalSize; dwrite(&uint32, sizeof(uint32), bmpP); uint16 = 0x00; dwrite(&uint16, sizeof(uint16), bmpP); /* reserved as 0 */ dwrite(&uint16, sizeof(uint16), bmpP); /* reserved as 0 */ /* bfOffBits: offset to image-data array */ uint32 = sizeof(int32_t)*11 + sizeof(int16_t)*5 + sizeof(char)*4*256; dwrite(&uint32, sizeof(uint32), bmpP); /* * BITMAPINFOHEADER struct */ uint32 = 40; /* when Windows-BMP, this is 40 */ dwrite(&uint32, sizeof(uint32), bmpP); sint32 = bmpw; /* biWidth */ dwrite(&sint32, sizeof(sint32), bmpP); sint32 = bmph; /* biHeight: down-top */ dwrite(&sint32, sizeof(sint32), bmpP); uint16 = 1; /* biPlanes: must be 1 */ dwrite(&uint16, sizeof(uint16), bmpP); uint16 = 8; /* biBitCount: 8bitColor */ dwrite(&uint16, sizeof(uint16), bmpP); uint32 = 0; /* biCompression: noCompression(BI_RGB) */ dwrite(&uint32, sizeof(uint32), bmpP); uint32 = 0; /* biSizeImage: when noComprsn, 0 is ok */ dwrite(&uint32, sizeof(uint32), bmpP); sint32 = 0; /* biXPelsPerMeter: resolution x; 0 ok */ dwrite(&sint32, sizeof(sint32), bmpP); sint32 = 0; /* biYPelsPerMeter: res y; 0 is ok */ dwrite(&sint32, sizeof(sint32), bmpP); uint32 = 0; /* biClrUsed: optimized color palette; not used */ dwrite(&uint32, sizeof(uint32), bmpP); uint32 = 0; /* biClrImportant: 0 is ok */ dwrite(&uint32, sizeof(uint32), bmpP); /* * RGBQUAD[256]: color palette */ /* palette[0]: background of glyphs */ uchar = 0xff; dwrite(&uchar, sizeof(uchar), bmpP); /* rgbBlue: B */ dwrite(&uchar, sizeof(uchar), bmpP); /* rgbGreen: G */ dwrite(&uchar, sizeof(uchar), bmpP); /* rgbRed: R */ uchar = 0; dwrite(&uchar, sizeof(uchar), bmpP); /* rgbReserved: must be 0 */ /* palette[1]: foreground of glyphs */ uchar = 0; for(i=0; i<4; i++) dwrite(&uchar, sizeof(uchar), bmpP); /* palette[1]: #000000 */ /* palette[2]: spacing */ uchar = COLOR_SPACING_BLUE; dwrite(&uchar, sizeof(uchar), bmpP); /* B */ uchar = COLOR_SPACING_GREEN; dwrite(&uchar, sizeof(uchar), bmpP); /* G */ uchar = COLOR_SPACING_RED; dwrite(&uchar, sizeof(uchar), bmpP); /* R */ uchar = 0; dwrite(&uchar, sizeof(uchar), bmpP); /* must be 0 */ /* palette[3]: out of dwidth over baseline */ uchar = COLOR_OVERBL_BLUE; dwrite(&uchar, sizeof(uchar), bmpP); /* B */ uchar = COLOR_OVERBL_GREEN; dwrite(&uchar, sizeof(uchar), bmpP); /* G */ uchar = COLOR_OVERBL_RED; dwrite(&uchar, sizeof(uchar), bmpP); /* R */ uchar = 0; dwrite(&uchar, sizeof(uchar), bmpP); /* must be 0 */ /* palette[4]: out of dwidth; under baseline */ uchar = COLOR_UNDERBL_BLUE; dwrite(&uchar, sizeof(uchar), bmpP); /* B */ uchar = COLOR_UNDERBL_GREEN; dwrite(&uchar, sizeof(uchar), bmpP); /* G */ uchar = COLOR_UNDERBL_RED; dwrite(&uchar, sizeof(uchar), bmpP); /* R */ uchar = 0; dwrite(&uchar, sizeof(uchar), bmpP); /* must be 0 */ /* palette[5] to palette[255]: not used */ for(i=5; i<256; i++){ uchar = 0x00; /* palette[5to255]: #000000 */ dwrite(&uchar, sizeof(uchar), bmpP); dwrite(&uchar, sizeof(uchar), bmpP); dwrite(&uchar, sizeof(uchar), bmpP); dwrite(&uchar, sizeof(uchar), bmpP); } /* * IMAGE DATA array */ for(y=bmph-1; y>=0; y--){ for(x=0; x=bmpw){ /* padding: long(4bytes) aligned */ uchar = 0; /* must pad with 0 */ dwrite(&uchar, sizeof(uchar), bmpP); }else{ if( (y%(font.h+spacing)= chars*font.h*font.w){ /* spacing over the last glyph */ uchar = 2; /* fill palette[2] */ }else uchar = *( bitmapP + tmp); dwrite(&uchar, sizeof(uchar), bmpP); } } } } return; } /* * 2. transfer bdf-font-file to bitmapAREA(onMemory) one glyph by one */ void assignBitmap(unsigned char *bitmapP, char *glyphP, int sizeglyphP, struct boundingbox glyph, int dw){ static char *hex2binP[]= { "0000","0001","0010","0011","0100","0101","0110","0111", "1000","1001","1010","1011","1100","1101","1110","1111" }; int d; /* decimal number translated from hexNumber */ int hexlen; /* a line length(without newline code) */ char binP[LINE_CHARMAX]; /* binary strings translated from decimal number */ static int nowchar = 0; /* number of glyphs handlled until now */ char *tmpP; char tmpsP[LINE_CHARMAX]; int bitAh, bitAw; /* bitA width, height */ int offtop, offbottom, offleft; /* glyph offset */ unsigned char *bitAP; unsigned char *bitBP; int i,j,x,y; /* * 2.1) change hexadecimal strings to a bitmap of glyph( called bitA) */ tmpP = strstr(glyphP, "\n"); if(tmpP == NULL){ /* if there is BITMAP\nENDCHAR in a given bdf-file */ *glyphP = '0'; *(glyphP+1) = '0'; *(glyphP+2) = '\n'; tmpP = glyphP + 2; sizeglyphP = 3; } hexlen = tmpP - glyphP; bitAw = hexlen * 4; bitAh = sizeglyphP / (hexlen+1); bitAP = malloc(bitAw * bitAh); /* address of bitA */ if(bitAP == NULL){ printf("error bitA malloc\n"); exit(EXIT_FAILURE); } for(i=0,x=0,y=0; i bitAP+bitAw*bitAh ){ printf("error: bitA pointer\n"); exit(EXIT_FAILURE); }else{ *(bitAP + y*bitAw + x) = binP[j] - '0'; } } } } /* * 2.2)make another bitmap area(called bitB) * bitB is sized to FONTBOUNDINGBOX */ bitBP = malloc(font.w * font.h); /* address of bitB */ if(bitBP == NULL){ printf("error bitB malloc\n"); exit(EXIT_FAILURE); } for(i=0; i= (-1)*font.offx+dw)){ if(i < font.h - (-1)*font.offy){ /* over baseline: palette[3] */ *(bitBP + i*font.w + j) = 3; }else{ /* under baseline: palette[4] */ *(bitBP + i*font.w + j) = 4; } }else{ /* in dwidth: palette[0] */ *(bitBP + i*font.w + j) = 0; } } } } /* * 2.3) copy bitA inside BBX (smaller) to bitB (bigger) * with offset-shifting; * a scope beyond bitA is already filled with palette[0or3] */ offleft = (-1)*font.offx + glyph.offx; /* offright = font.w - glyph.w - offleft; */ offbottom = (-1)*font.offy + glyph.offy; offtop = font.h - glyph.h - offbottom; for(i=0; i=offtop+glyph.h ) ; /* do nothing */ else for(j=0; j=offleft+glyph.w ) ; /* do nothing */ else *(bitBP + i*font.w + j) = *(bitAP + (i-offtop)*bitAw + (j-offleft)); } /* * 2.4) copy bitB to bitmapAREA */ for(i=0; i= PARAM_MAX){ printf("error: too many arguments\n"); exit(EXIT_FAILURE); } }else if( (argv[i][j]=='s') || (argv[i][j]=='c')) { *(sP+dst) = '-'; dst++; *(sP+dst) = argv[i][j]; dst++; }else if( isdigit(argv[i][j]) == 0 ){ /* not [0-9] */ printf("error: invalid option -- '%c'\n", argv[i][j]); exit(EXIT_FAILURE); }else if( argv[i][j+1] == '\0' ){ *(sP+dst) = argv[i][j]; dst++; *(sP+dst) = '\0'; strcpy(paramP[n], sP); dst=0; n++; if(n >= PARAM_MAX){ printf("error: too many arguments\n"); exit(EXIT_FAILURE); } }else{ *(sP+dst) = argv[i][j]; dst++; } } }else{ /* not command-line options */ for(j=0; j<(int)strlen(argv[i]); j++){ *(sP+dst) = argv[i][j]; dst++; } *(sP+dst) = '\0'; strcpy(paramP[n], sP); dst=0; n++; memset(sP,0,LINE_CHARMAX); if(n >= PARAM_MAX){ printf("error: too many arguments\n"); exit(EXIT_FAILURE); } } } free(sP); /* interpretting arguments */ for(i=0, flag=0; i 1024) colchar = 1024; /* spacing is limited from 0 to 32 */ if(spacing < 0) spacing = 0; else if(spacing > 32) spacing = 32; /* checkEndian */ checkEndian(); /* * prepare to read&write files */ readP = fopen(readFilename, "r"); if(readP == NULL){ printf("bdf2bmp: '%s' does not exist\n", readFilename); exit(EXIT_FAILURE); } /* Does writeFilename already exist? */ if((iflag==ON) && (stat(writeFilename, &fileinfo)==0)){ fprintf(stderr, "bdf2bmp: overwrite '%s'? ", writeFilename); c = fgetc(stdin); if((c=='y') || (c=='Y')) ; /* go next */ else /* printf("not overwrite\n"); */ exit(EXIT_FAILURE); } writeP=fopen(writeFilename, "wb"); if(writeP == NULL){ printf("error: cannot write '%s'\n", writeFilename); exit(EXIT_FAILURE); } /* read bdf-font-file */ bitmapP = readBdfFile(bitmapP, readP); fclose(readP); /* write bmp-image-file */ writeBmpFile(bitmapP, spacing, colchar, writeP); tmp = fclose(writeP); if(tmp == EOF){ printf("error: cannot write '%s'\n", writeFilename); free(bitmapP); exit(EXIT_FAILURE); } free(bitmapP); return EXIT_SUCCESS; }