1 /* x2ch.c 1.1 87/02/05 2 * 3 * Font translation for X font-style fonts to character format. 4 * 5 * Use: x2ch [ -p# ] fontfile [ character_list ] 6 * 7 * Reads "fontfile" from current directory (or if not found, 8 * from BITDIR defined below) and converts it to a character font format 9 * editable by real people, and convertable BACK to X format by the 10 * ch2x program. The -p option specifies the "point size" of the font. 11 * If no "-p#" is specified, the pointsize is 10. Output goes to stdout. 12 */ 13 /* #define DEBUG /* if defined, statistics are printed to stderr */ 14 15 #include <stdio.h> 16 #include "xfont.h" 17 18 19 #define DIRSIZ 256 20 #define BITDIR "/usr/new/lib/X/font" 21 22 23 struct FontData FH; 24 #define first FH.firstChar 25 #define last FH.lastChar 26 short bitmapindex[DIRSIZ + 1];/* bit offsets in bitmap */ 27 short widths[DIRSIZ + 1]; /* widths calculated from but offsets */ 28 char *charbits; /* pointer to start of bitmap */ 29 char **lineptr; /* pointers to start of each line of bitmap */ 30 int pointsize = 10; /* can only be changed from command line */ 31 int tmp; /* used for various short-lived things */ 32 int *bitcount; /* place to hold count of bits on a particular 33 line in bitmap - used to find the baseline */ 34 35 char IName[100]; /* input file name building place */ 36 unsigned char defascii[DIRSIZ]; /* default characters to print */ 37 unsigned char *charswanted = defascii; 38 39 40 main(argc, argv) 41 int argc; 42 char **argv; 43 { 44 register int i; 45 register int j; 46 int FID; 47 48 if (argc < 2 || argc > 4) { 49 usage: 50 error("usage: %s [ -p# ] filename [ character-list ]", argv[0]); 51 } 52 if (argv[1][0] == '-') { 53 argv++; 54 if (argv[0][1] != 'p') 55 goto usage; 56 pointsize = atoi(&(argv[0][2])); 57 } 58 for (i = 0; i < DIRSIZ; i++) { 59 bitmapindex[i] = 0; 60 widths[i] = 0; 61 defascii[i] = i; 62 } 63 if (argc == 3) 64 charswanted = (unsigned char *) argv[2]; 65 66 /* 67 * find font in BITDIR or current directory, also trying to 68 * tack on the ".onx" extension onto the filename 69 */ 70 ++argv; 71 sprintf(IName, "%s/%s.onx", BITDIR, *argv); 72 if ((FID = open(*argv, 0)) < 0) { 73 if ((FID = open(IName, 0)) < 0) { 74 sprintf(IName, "%s.onx", *argv); 75 if ((FID = open(IName, 0)) < 0) { 76 sprintf(IName, "%s/%s", BITDIR, *argv); 77 if ((FID = open(IName, 0)) < 0) 78 error("Can't find %s", *argv); 79 } 80 } 81 } 82 83 if (read(FID, &FH, sizeof FH) != sizeof FH) 84 error("no header in Font file."); 85 if (first < 0 || last >= DIRSIZ || last <= first) 86 error("font boundaries (%d,%d) out of range", first, last); 87 if (FH.bmWidth <= 0 || FH.bmWidth >= 20000 || 88 FH.bmHeight <= 0 || FH.bmHeight >= 20000) 89 error("dimensions (%d,%d) out of range",FH.bmWidth,FH.bmHeight); 90 i = (((FH.bmWidth + 15) >> 3) &~ 1) * FH.bmHeight; 91 charbits = (char *) malloc(i); 92 93 #ifdef DEBUG 94 fprintf(stderr,"Bit Map Ptr = %d\nBitMap Width = %d\nBit Map Height = %d\nBitsPerPixel = %d\nFirst Character = %d\nLast Character = %d\nLeft Array = %d\nBaseLine = %d\nSpace Index = %d\nFixed Width = %d\nbit map size = %d\n", FH.bitmapPtr, FH.bmWidth, FH.bmHeight, FH.bitsPerPixel, FH.firstChar, FH.lastChar, FH.leftArray, FH.baseline, FH.spaceIndex, FH.fixedWidth, i); 95 #endif 96 97 lseek (FID, (long) FH.bitmapPtr, 0); 98 if (read(FID, charbits, i) != i) 99 error("bit map (%d chars) not in Font file", i); 100 101 if (FH.fixedWidth == 0) { 102 i = (last - first + 2) * sizeof (short); 103 #ifdef DEBUG 104 fprintf(stderr, "width array size = %d\n", i); 105 #endif 106 lseek (FID, (long) FH.leftArray, 0); 107 if (read(FID, &bitmapindex[first], i) != i) 108 error("width map not in Font file"); 109 } else { 110 for (i = first + 1; i <= last + 1; i++) 111 bitmapindex[i] = bitmapindex[i - 1] + FH.fixedWidth; 112 } 113 /* 114 * figure out character widths from "leftarray" 115 */ 116 #ifdef DEBUG 117 fprintf(stderr,"left,widths:\n"); 118 #endif 119 for (i = first; i <= last; i++) { 120 if ((widths[i] = bitmapindex[i + 1] - bitmapindex[i]) < 0) 121 error ("inconsistent width table"); 122 #ifdef DEBUG 123 fprintf(stderr,"%03d:%5d,%6d\n", i, bitmapindex[i], widths[i]); 124 #endif 125 } 126 lineptr = (char **) malloc((FH.bmHeight + 2) * sizeof (char *)); 127 j = ((FH.bmWidth + 15) >> 3) &~ 1; 128 lineptr[0] = charbits; 129 for (i = 1; i <= FH.bmHeight; i++) { 130 lineptr[i] = lineptr[i - 1] + j; 131 } 132 133 /* 134 * If not given a baseline, try to figure one out by counting the 135 * bits in a given row. When the number falls suddenly, that's the 136 * baseline. This is not guaranteed to work. 137 */ 138 if (--FH.baseline < 0) { 139 tmp = 0; 140 bitcount = (int *) malloc((FH.bmHeight + 2) * sizeof (int)); 141 for (i = 0; i < FH.bmHeight; i++) { 142 bitcount[i] = 0; 143 for (j = 0; j < FH.bmWidth; j++) { 144 if (bitset(lineptr[i], j)) 145 bitcount[i]++; 146 } 147 tmp += bitcount[i]; 148 #ifdef DEBUG 149 fprintf(stderr, "bitcount[%d] == %d\n", i, bitcount[i]); 150 #endif 151 } 152 tmp /= FH.bmHeight + 1; 153 #ifdef DEBUG 154 fprintf(stderr, "average == %d\n", tmp); 155 #endif 156 for (i = 1; i < FH.bmHeight; i++) { 157 if (bitcount[i-1] > tmp && bitcount[i] < (tmp >> 1)) 158 FH.baseline = i - 1; 159 } 160 if (FH.baseline < 0) 161 FH.baseline = 0; 162 } 163 164 printf("fontheader\ndesiz %d\nmag 1000\n", pointsize); 165 printf("rot 0\ncadv 0\nladv 1\nid 0\nres 75\n"); 166 167 for (i = 0; i < DIRSIZ; i++) { 168 j = charswanted[i]; 169 if (i > 0 && j == 0) 170 break; 171 if (widths[j]) { 172 register int k; 173 register int l; 174 175 printf(":%d, width = %d.00\n", j, widths[j]); 176 177 for (k = 0; k < FH.bmHeight; k++) { 178 for (l = 0; l < widths[j]; l++) { 179 if (bitset(lineptr[k], bitmapindex[j]+l)) { 180 if (l == 0 && k == FH.baseline) 181 putchar('X'); 182 else 183 putchar('@'); 184 } else { 185 if (l == 0 && k == FH.baseline) 186 putchar('x'); 187 else 188 putchar('.'); 189 } 190 } 191 putchar('\n'); 192 } 193 194 putchar('\n'); 195 } 196 } 197 exit(0); 198 } 199 200 201 /*----------------------------------------------------------------------------* 202 | Routine: error (format_string, argument1, argument2.... ) 203 | 204 | Results: fprints a message to standard error, then exits with error 205 | code 1 206 | 207 | Side Efct: This routine does NOT return 208 *----------------------------------------------------------------------------*/ 209 210 /*VARARGS1*/ 211 error(string, a1, a2, a3, a4) 212 char *string; 213 { 214 fprintf(stderr, "x2ch: "); 215 fprintf(stderr, string, a1, a2, a3, a4); 216 fprintf(stderr, "\n"); 217 exit(1); 218 } 219 220 221 /*----------------------------------------------------------------------------* 222 | Routine: bitset (bitstream pointer, bit number) 223 | 224 | Results: returns nonzero if a bit is set in a supplied bit stream. 225 | No range checking is done on anything. Bit order is least 226 | significant to most significant. 227 *----------------------------------------------------------------------------*/ 228 229 bitset(stream, bit) 230 char *stream; 231 register int bit; 232 { 233 register char *p; 234 235 p = stream + (bit >> 3); 236 return ((*p) & (1 << (bit & 7))); 237 } 238