1 /* ch2x.c 1.1 87/02/05 2 * 3 * Font translation to X format from character format. 4 * 5 * Use: ch2x [ -i -s ] charfile > xfontfile 6 * 7 * Takes input from charfile (which must be in the format written 8 * by one of the xxx2ch programs), converts to X format and writes it 9 * to stdout. If charfile is missing, stdin is read. The -i flag tells 10 * ch2x to ignore the character codes at the start of each glyph 11 * definition, and pack the glyphs in consecutive code positions starting 12 * with 0. Unlike other conversion programs, white space around a glyph 13 * is preserved. Therefore, the -s option is ignored. 14 */ 15 16 #include <stdio.h> 17 #include "xfont.h" 18 19 20 #define RES 75 /* for xfont, resolution is 75 */ 21 #define MAXLINE 300 22 #define GLYPHSPACE (MAXLINE * MAXLINE / 8) 23 #define DIRSIZ 256 /* maximum # of entries */ 24 25 26 char * malloc(); 27 char * index(); 28 29 struct FontData FH; /* font file header */ 30 struct GlyphData { 31 short up; 32 short down; 33 short left; 34 short right; 35 short nbytes; 36 short width; 37 char *ptr; 38 } g[DIRSIZ]; /* table of glyph definitions */ 39 short leftarea[DIRSIZ]; 40 char bitmap[GLYPHSPACE]; 41 char * newbitmap; 42 43 int code; 44 int printwidth, width, length, refv, refh; 45 int totalwidth, maxleft, maxup, maxdown; 46 47 int ignorecode = 0; 48 FILE * filep; 49 char ibuff[MAXLINE]; 50 51 52 main(argc,argv) 53 int argc; 54 char **argv; 55 { 56 register int i; 57 register int j; 58 register int codeindex; 59 register char *chp; 60 register char *bitp; 61 register int bit; 62 float par; 63 64 65 while (argc > 1 && argv[1][0] == '-') { 66 switch(argv[1][1]) { 67 case 'i': 68 ignorecode = 1; 69 break; 70 71 case 's': 72 break; 73 default: 74 error("%s, unknown option flag", argv[1]); 75 } 76 argc--; argv++; 77 } 78 79 if (argc == 2) { 80 if ((filep = fopen (argv[1], "r")) == NULL) 81 error("can't open file \"%s\"", argv[1]); 82 } else filep = stdin; 83 84 codeindex = 0; 85 totalwidth = 0; 86 maxleft = 0; 87 maxup = 0; 88 maxdown = 0; 89 FH.fixedWidth = -1; 90 for (i = 0; i < DIRSIZ; g[i++].ptr = (char *) 0); 91 92 if (fgets(ibuff, MAXLINE, filep) == NULL || strcmp(ibuff, "fontheader\n")) 93 error("not a character font file"); 94 95 while (fgets(ibuff, MAXLINE, filep) != NULL) { 96 if (index(ibuff, '\n') == NULL) 97 error("input line too long"); 98 99 if (ibuff[0] == ':') { 100 if (sscanf (ibuff, ":%d, width = %f", &code, &par) != 2) 101 error("bad glyph header \"%s\"", ibuff); 102 if (ignorecode) codeindex++; else codeindex = code; 103 if (codeindex < 0 || codeindex >= DIRSIZ) 104 error("code (%d) out of range", codeindex); 105 printwidth = par + 0.5; 106 107 chp = &ibuff[0]; 108 bitp = &bitmap[-1]; 109 if (fgets(chp, MAXLINE, filep) == NULL) 110 error("unexpected end of input"); 111 width = strlen(chp) - 1; 112 refv = -1; 113 114 for (length = 0; *chp != '\n'; length++) { 115 bit = 0x100; 116 for (i = 0; i < width; i++, chp++) { 117 if (bit == 0x100) { 118 if (++bitp >= &bitmap[GLYPHSPACE]) 119 error ("out of glyph space"); 120 *bitp = 0; 121 bit = 1; 122 } 123 switch (*chp) { 124 case '.': 125 break; 126 case 'x': 127 refh = i; 128 refv = length; 129 break; 130 case 'X': 131 refh = i; 132 refv = length; 133 case '@': 134 case '*': 135 *bitp |= bit; 136 break; 137 default: 138 error("illegal character '%c' in map.", *chp); 139 } /* switch */ 140 bit <<= 1; 141 } /* for i */ 142 chp = &ibuff[0]; 143 if (fgets(chp, MAXLINE, filep) == NULL) 144 error("unexpected end of input"); 145 } /* for length */ 146 147 if (refv < 0) error("no reference point in glyph %d.", code); 148 149 g[codeindex].up = refv; 150 g[codeindex].down = length - refv; 151 g[codeindex].right = width - refh; 152 if (g[codeindex].right > printwidth) 153 printwidth = g[codeindex].right; 154 g[codeindex].left = refh; 155 g[codeindex].nbytes = bitp - bitmap + 1; 156 g[codeindex].width = printwidth; 157 totalwidth += printwidth; 158 if (FH.fixedWidth == -1) 159 FH.fixedWidth = printwidth; 160 if (FH.fixedWidth != printwidth) 161 FH.fixedWidth = 0; 162 if (g[codeindex].left > maxleft) maxleft = g[codeindex].left; 163 if (g[codeindex].up > maxup) maxup = g[codeindex].up; 164 if (g[codeindex].down > maxdown) maxdown = g[codeindex].down; 165 166 /* copy the bits to private place */ 167 if ((g[codeindex].ptr = malloc(g[codeindex].nbytes)) == NULL) 168 error("out of memory reading in file"); 169 bcopy(bitmap, g[codeindex].ptr, g[codeindex].nbytes); 170 } /* if ibuff == : */ 171 } /* while not EOF */ 172 173 if (totalwidth == 0) 174 error("empty font"); 175 176 /* 177 * Fill in the "fontData" header for this font. fixedWidth is already set. 178 */ 179 FH.waste = 0; 180 FH.bitsPerPixel = 1; 181 FH.spaceIndex = 32; /* we can only guess */ 182 for (i = 0; g[i].ptr == NULL; i++) 183 ; 184 FH.firstChar = i; 185 for (i = DIRSIZ - 1; g[i].ptr == NULL; i--) 186 ; 187 FH.lastChar = i; 188 FH.bmHeight = maxup + maxdown; 189 FH.baseline = maxup + 1; 190 FH.leftArray = sizeof (FH); 191 FH.bitmapPtr = FH.leftArray + (FH.lastChar-FH.firstChar+2) * sizeof(short); 192 193 /* 194 * calculate "leftarea" - the pointers for each glyph into the bitmap 195 */ 196 leftarea[FH.firstChar] = 0; 197 for (i = FH.firstChar; i <= FH.lastChar; i++) { 198 if (g[i].ptr == NULL) { 199 FH.fixedWidth = 0; 200 leftarea[i + 1] = leftarea[i]; 201 } else { 202 leftarea[i + 1] = leftarea[i] + g[i].width + maxleft; 203 totalwidth += maxleft; 204 } 205 } 206 FH.bmWidth = totalwidth; 207 width = ((totalwidth + 15) >> 3) & ~1; 208 newbitmap = bitmap; 209 if (width > GLYPHSPACE) 210 if ((newbitmap = malloc(width)) == NULL) 211 error("out of memory writing file"); 212 213 vwrite(&FH, sizeof(FH)); 214 vwrite(&leftarea[FH.firstChar],(FH.lastChar-FH.firstChar+2)*sizeof(short)); 215 /* 216 * Calculate and write out the "strike" bitmap 217 */ 218 for (length = 0; length < FH.bmHeight; length++) { 219 bitp = newbitmap; 220 *bitp = 0; 221 i = 1; 222 for (codeindex = FH.firstChar; codeindex <= FH.lastChar; codeindex++) { 223 if (g[codeindex].ptr != NULL) { 224 for (j = -maxleft; j < g[codeindex].width; j++) { 225 if (bitset(&g[codeindex], j, maxup)) { 226 *bitp |= i; 227 } 228 i <<= 1; 229 if (i == 0x100) { 230 *++bitp = 0; 231 i = 1; 232 } 233 } 234 } 235 } 236 vwrite(newbitmap, width); 237 maxup--; 238 } 239 exit(0); 240 } 241 242 243 /*----------------------------------------------------------------------------* 244 | Routine: vwrite (buffer, buffer_size) 245 | 246 | Results: writes out character array "buffer" of size "buffer_size" 247 | in sizes that "write" can handle 248 *----------------------------------------------------------------------------*/ 249 250 vwrite(buf, bufsize) 251 char *buf; 252 int bufsize; 253 { 254 int tsize = 0; 255 256 while (bufsize) { 257 buf += tsize; 258 if ((tsize = write(1, buf, bufsize)) < 0) { 259 perror("ch2x: write failed"); 260 exit(-1); 261 } 262 bufsize -= tsize; 263 } 264 } 265 266 267 /*----------------------------------------------------------------------------* 268 | Routine: bitset (GlyphData_pointer, x_position, y_position) 269 | 270 | Results: Given a Glyph definition and an x,y position (relative to the 271 | reference point of the glyph) bitset returns non-zero if the 272 | glyph has a pixel set at that point. 273 *----------------------------------------------------------------------------*/ 274 275 /*VARARGS1*/ 276 bitset(g, x, y) 277 register struct GlyphData *g; 278 register int x; 279 register int y; 280 { 281 register char *p; 282 283 x += g->left; 284 y = g->up - y; 285 if (x < 0 || y < 0 || x >= (g->left+g->right) || y >= (g->up+g->down)) 286 return(0); 287 p = g->ptr + (x >> 3) + y * ((g->left + g->right + 7) >> 3); 288 return( *p & (1 << (x&7)) ); 289 } 290 291 292 /*----------------------------------------------------------------------------* 293 | Routine: error (format_string, argument1, argument2.... ) 294 | 295 | Results: fprints a message to standard error, then exits with error 296 | code 1 297 | 298 | Side Efct: This routine does NOT return 299 *----------------------------------------------------------------------------*/ 300 301 /*VARARGS1*/ 302 error(string, a1, a2, a3, a4) 303 char *string; 304 { 305 fprintf(stderr, "ch2x: "); 306 fprintf(stderr, string, a1, a2, a3, a4); 307 fprintf(stderr, "\n"); 308 exit(1); 309 } 310