1 /******************************************************************** 2 * 3 * Harris - Emulator specific font stuff: bitmap files. 4 * 5 * @(#)font2.c 1.2 (CWI) 87/07/10 6 * 7 *******************************************************************/ 8 #include <sys/types.h> 9 #include <sys/stat.h> 10 #include <sys/file.h> 11 #include <errno.h> 12 #include "the.h" 13 #include "defs.h" /* harris font definitions */ 14 15 16 #define BYTE 8 17 18 19 struct chardata { 20 short charno; /* character number */ 21 int XO, YO; /* origin of char rel. to troff positions */ 22 int width, height; /* scaled size in bits */ 23 char *cbitmap; /* bitmap of character */ 24 short nbytes; /* length of bitmap */ 25 struct chardata *nextchar; 26 }; 27 28 struct fontadmin { 29 short physical; 30 short size; 31 struct chardata *ch[128+1]; /* we start at index 1 */ 32 struct fontadmin *f; 33 }; 34 35 36 37 private struct fontadmin *currentfnt; 38 private struct fontadmin firstf; 39 40 extern short *pstab; 41 extern int size; 42 extern char buffer[]; 43 extern int hpos, vpos, vorigin; 44 extern int virtRES; 45 extern int debug, dbg; 46 extern int slant; 47 extern double slantoffset; 48 49 extern int errno; 50 51 52 char *getfile(); 53 54 struct fontadmin *findfont(); 55 struct fontadmin *falloc(); 56 57 extern char *malloc(); 58 59 60 61 62 initfonts() 63 { 64 currentfnt = (struct fontadmin *) 0; /* zero it out to start! */ 65 firstf.physical = 0; 66 firstf.size = 0; 67 } 68 69 70 71 /* 72 * putcode: get the necessary character data and write it. 73 * 74 * This function should be in put.c, but it knows too much 75 * about the internal structure of the fonts, so it 76 * is here. 77 */ 78 79 int M[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707, 80 0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff }; 81 int N[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8, 82 0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 }; 83 int strip[] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff }; 84 85 86 putcode(code,f) 87 int code; int f; /* character to print */ 88 { 89 struct chardata *foundc; /* pointer to found character */ 90 char *scanp; /* position to place character in buffer */ 91 char *sc; /* real position to place char in buffer */ 92 char *cm; 93 int nvpos; /* new vertical position */ 94 int nhpos; /* new horizontal position */ 95 int nhbyte; /* byte index of horizontal position */ 96 int offbit, off8; /* bit offset from byte index of hor. pos.*/ 97 double sloffset; /* amount of offset due to slant */ 98 int bwidth, cnt; /* width of bitmap in bytes */ 99 int h; /* height count */ 100 register unsigned int fontdata; 101 unsigned char *to, *from; 102 unsigned int n; 103 int scan_inc; 104 105 if(currentfnt->physical != f || currentfnt->size != size) { 106 currentfnt = findfont(f); 107 } 108 foundc = currentfnt->ch[code]; 109 if( foundc == (struct chardata *)0 ) 110 return; 111 112 nvpos = PHYS(vpos) - vorigin - foundc->height + foundc->YO; 113 nhpos = PHYS(hpos) + foundc->XO; 114 bwidth = (foundc->width + 7)/BYTE; 115 cm = foundc->cbitmap; 116 117 if((nvpos >= NLINES) || (nvpos + foundc->height <= 0)) 118 return; 119 if( nhpos < 0 ) /* ignore chars left of left margin */ 120 return; 121 122 /* the following is an ugly optimization: since slant will usually 123 * be zero, and we can save a whole lot of time if that is so, 124 * have a duplicate (faster) loop for that case (DD) 125 */ 126 127 if( slant == 0 ) { 128 129 nhbyte = nhpos / BYTE; 130 offbit = nhpos % BYTE; 131 off8 = 8 - offbit; 132 scanp = buf0p + nvpos * BYTES_PER_LINE + nhbyte; 133 scan_inc = BYTES_PER_LINE - bwidth; 134 135 for(h = 0; h < foundc->height; h++) { 136 137 if (scanp + bwidth >= BUFBOTTOM) 138 break; 139 140 cnt = bwidth; 141 if (scanp >= BUFTOP) { 142 do { 143 fontdata = *(unsigned *)cm; 144 cm += 4; 145 if( cnt < 4 ) 146 fontdata &= strip[cnt]; 147 *(unsigned int *)scanp |= (fontdata >> offbit) & M[off8]; 148 scanp++; /* _char_ increment */ 149 *(unsigned int *)scanp |= (fontdata << off8) & N[off8]; 150 scanp += 3; /* to next _word_ */ 151 cnt -= 4; 152 } while( cnt > 0 ); 153 } 154 scanp += scan_inc + cnt; 155 cm += cnt; 156 } 157 } else { /* we have to add in a slant offset for each row */ 158 159 scanp = buf0p + nvpos * BYTES_PER_LINE; 160 sloffset = slantoffset * (foundc->height - foundc->YO); 161 162 for( h = 0; 163 h < foundc->height; 164 h++, scanp += BYTES_PER_LINE, sloffset -= slantoffset ){ 165 166 nhbyte = (nhpos + (int)sloffset) / BYTE; 167 offbit = (nhpos + (int)sloffset) % BYTE; 168 off8 = 8 - offbit; 169 sc = scanp + nhbyte; 170 171 if( sc <= BUFTOP ) 172 continue; 173 174 if( sc + bwidth >= BUFBOTTOM ) 175 break; 176 177 to = (unsigned char *)sc; 178 from = (unsigned char *)&cm[ h*bwidth ]; 179 cnt = bwidth; 180 while (cnt--) { 181 n = *from++; 182 *to++ |= n >> offbit; 183 *to |= n << off8; 184 } 185 } 186 } 187 } 188 189 190 191 192 193 /* 194 * findfont(f): Try to find font f (in current size). 195 * If the font in this size is not already loaded, try to load it. 196 */ 197 198 199 struct fontadmin * 200 findfont(f) 201 int f; 202 { 203 struct fontadmin *p = &firstf; 204 char file[BUFSIZ], *fbuf; 205 206 207 DBGPRINT(0, ("Searching for %d size %d\n", f, size )); 208 /* 209 * search list for desired font and size 210 */ 211 212 while( p->physical != 0 ) { 213 214 if( p->physical == f && p->size == size ) 215 return(p); 216 #ifdef DEBUGABLE 217 else if(p->physical > 10000 || p->physical < 10) 218 error(FATAL, "odd font: %d!\n",p->physical); 219 #endif 220 else 221 p = p->f; 222 } 223 224 225 /* 226 * not in list, so make it 227 */ 228 229 p->physical = f; 230 p->size = size; 231 p->f = falloc(); 232 p->f->physical = 0; 233 234 235 sprintf(file,"%s/%d/%d", BITS, f, pstab[ size ] ); 236 fbuf = getfile(file); /* getfile exits if unsuccessful */ 237 238 DBGPRINT(0, ("Loading bitmaps for font %d size %d\n", f, size)); 239 loadbits( fbuf, p->ch ); 240 241 return( p ); 242 } 243 244 245 246 /* 247 * loadbits: reconstruct the linked char list from buf, 248 * and put it into the given array. 249 */ 250 251 252 loadbits( buf, cha ) 253 char *buf; 254 struct chardata *cha[]; 255 { 256 struct chardata *firstc, *ch; 257 unsigned offset = 0; 258 int i; 259 260 ch = firstc = (struct chardata *)buf; 261 262 /* note we employ a trick here: we know that all 263 * the addresses (->nextchar and ->cbitmap) are 264 * garbage, yet still the list must have been 265 * terminated with ch->nextchar == 0, so we can 266 * still tell where it was supposed to end. 267 */ 268 269 while( ch->nextchar != (struct chardata *)0 ) 270 { 271 offset += sizeof( struct chardata ); 272 ch->cbitmap = (char *)(buf + offset); 273 offset += ch->nbytes; 274 ch->nextchar = (struct chardata *)(buf + offset); 275 276 ch = ch->nextchar; 277 } 278 /* clean up last one */ 279 offset += sizeof( struct chardata ); 280 ch->cbitmap = (char *)(buf + offset); 281 282 /* 283 * now go through and fill up the array 284 */ 285 ch = firstc; 286 for( i=1; i<=128; i++ ) 287 { 288 if( i == ch->charno ) 289 { 290 cha[i] = ch; 291 ch = ch->nextchar; 292 } 293 else 294 cha[i] = 0; 295 } 296 } 297 298 299 300 struct fontadmin * 301 falloc() 302 { 303 register char *p; 304 305 if(( p = malloc(sizeof(struct fontadmin))) == (char *) 0) 306 error(FATAL, "Falloc"); 307 return((struct fontadmin *) p); 308 } 309 310 311 312 313 /* 314 * get the contents of the file, and return a pointer to them. 315 * All errors result in death. 316 * 317 */ 318 319 320 char * 321 getfile(file) 322 char *file; 323 { 324 struct stat statbuf; 325 char *filebuf, *malloc(); 326 int fdi; 327 328 if( stat(file, &statbuf) == -1 ) 329 error(FATAL, "Can't get file status: %s (error %d)", file, errno); 330 331 if((statbuf.st_mode & S_IFMT) != S_IFREG) 332 error(FATAL, "File %s not a regular file", file); 333 334 if((fdi = open(file, O_RDONLY)) < 0 ) 335 error(FATAL, "Can not open %s (error %d)", file, errno ); 336 337 if((filebuf = malloc( (unsigned int)statbuf.st_size )) == (char *)0) 338 error(FATAL, "Not enough room for file %s!", file); 339 340 if(read(fdi, filebuf, (int)statbuf.st_size) != statbuf.st_size) 341 error(FATAL, "Read error on %s", file); 342 343 (void) close( fdi ); 344 return( filebuf ); 345 } 346