1 /* Unicode | PostScript 2 * start end | offset font name 3 * 0x0000 0x00ff 0x00 LucidaSansUnicode00 4 */ 5 #include <u.h> 6 #include <libc.h> 7 #include <bio.h> 8 #include "common.h" 9 #include "tr2post.h" 10 #include "comments.h" 11 #include "path.h" 12 13 /* Postscript font names, e.g., `LucidaSansUnicode00' 14 * names may only be added because reference to the 15 * names is made by indexing into this table. 16 */ 17 static struct pfnament *pfnafontmtab = 0; 18 static int pfnamcnt = 0; 19 int curpostfontid = -1; 20 int curfontsize = -1; 21 int curtrofffontid = -1; 22 static int curfontpos = -1; 23 static int fontheight = 0; 24 static int fontslant = 0; 25 26 /* This is troffs mounted font table. It is an anachronism resulting 27 * from the design of the APS typesetter. fontmnt is the 28 * number of positions available. fontmnt is really 11, but 29 * should not be limited. 30 */ 31 int fontmnt = 0; 32 char **fontmtab; 33 34 struct troffont *troffontab = 0; 35 36 int troffontcnt = 0; 37 38 void 39 mountfont(int pos, char *fontname) { 40 int i; 41 42 if (debug) fprint(2, "mountfont(%d, %s)\n", pos, fontname); 43 if (pos < 0 || pos >= fontmnt) 44 error(FATAL, "cannot mount a font at position %d,\n can only mount into postions 0-%d\n", 45 pos, fontmnt-1); 46 47 i = strlen(fontname); 48 fontmtab[pos] = galloc(fontmtab[pos], i+1, "mountfont():fontmtab"); 49 strcpy(fontmtab[pos], fontname); 50 if (curfontpos == pos) curfontpos = -1; 51 } 52 53 void 54 settrfont(void) { 55 if (curfontpos == fontpos) return; 56 57 if (fontmtab[fontpos] == 0) 58 error(FATAL, "Font at position %d was not initialized, botch!\n", fontpos); 59 60 curtrofffontid = findtfn(fontmtab[fontpos], 1); 61 if (debug) fprint(2, "settrfont()-> curtrofffontid=%d\n", curtrofffontid); 62 curfontpos = fontpos; 63 if (curtrofffontid < 0) { 64 int i; 65 66 error(WARNING, "fontpos=%d\n", fontpos); 67 for (i=0; i<fontmnt; i++) 68 if (fontmtab[i] == 0) 69 error(WARNING, "fontmtab[%d]=0x0\n", i); 70 else 71 error(WARNING, "fontmtab[%d]=%s\n", i, fontmtab[i]); 72 exits("settrfont()"); 73 } 74 } 75 76 void 77 setpsfont(int psftid, int fontsize) { 78 if (psftid == curpostfontid && fontsize == curfontsize) return; 79 if (psftid >= pfnamcnt) 80 error(FATAL, "Postscript font index=%d used but not defined, there are only %d fonts\n", 81 psftid, pfnamcnt); 82 83 endstring(); 84 if (pageon()) { 85 Bprint(Bstdout, "%d /%s f\n", fontsize, pfnafontmtab[psftid].str); 86 if ( fontheight != 0 || fontslant != 0 ) 87 Bprint(Bstdout, "%d %d changefont\n", fontslant, (fontheight != 0) ? fontheight : fontsize); 88 pfnafontmtab[psftid].used = 1; 89 curpostfontid = psftid; 90 curfontsize = fontsize; 91 } 92 } 93 94 /* find index of PostScript font name in table 95 * returns -1 if name is not in table 96 * If insflg is not zero 97 * and the name is not found in the table, insert it. 98 */ 99 int 100 findpfn(char *fontname, int insflg) { 101 char *tp; 102 int i; 103 104 for (i=0; i<pfnamcnt; i++) { 105 if (strcmp(pfnafontmtab[i].str, fontname) == 0) 106 return(i); 107 } 108 if (insflg) { 109 tp = galloc(pfnafontmtab, sizeof(struct pfnament)*(pfnamcnt+1), "findpfn():pfnafontmtab"); 110 if (tp == 0) 111 return(-2); 112 pfnafontmtab = (struct pfnament *)tp; 113 i = strlen(fontname); 114 pfnafontmtab[pfnamcnt].str = galloc(0, i+1, "findpfn():pfnafontmtab[].str"); 115 strncpy(pfnafontmtab[pfnamcnt].str, fontname, i); 116 pfnafontmtab[pfnamcnt].str[i] = '\0'; 117 pfnafontmtab[pfnamcnt].used = 0; 118 return(pfnamcnt++); 119 } 120 return(-1); 121 } 122 123 char postroffdirname[] = "/sys/lib/postscript/troff"; /* "/sys/lib/postscript/troff/"; */ 124 char troffmetricdirname[] = "/sys/lib/troff/font"; /* "/sys/lib/troff/font/devutf/"; */ 125 126 int 127 readpsfontdesc(char *fontname, int trindex) { 128 int errorflg = 0, line = 1, rv, start, end, offset; 129 int startfont, endfont, startchar, endchar, i, pfid; 130 char psfontnam[128]; 131 struct troffont *tp; 132 Biobuf *bfd; 133 Biobufhdr *Bfd; 134 static char *filename = 0; 135 136 if (debug) 137 fprint(2, "readpsfontdesc(%s,%d)\n", fontname, trindex); 138 filename = galloc(filename, strlen(postroffdirname)+1+strlen(fontname)+1, 139 "readpsfontdesc: cannot allocate memory\n"); 140 sprint(filename, "%s/%s", postroffdirname, fontname); 141 142 bfd = Bopen(filename, OREAD); 143 if (bfd == 0) { 144 error(WARNING, "cannot open file %s\n", filename); 145 return(0); 146 } 147 Bfd = &bfd->Biobufhdr; 148 149 do { 150 offset = 0; 151 if ((rv=Bgetfield(Bfd, 'd', &start, 0)) == 0) { 152 errorflg = 1; 153 error(WARNING, "file %s:%d illegal start value\n", filename, line); 154 } else if (rv < 0) break; 155 if ((rv=Bgetfield(Bfd, 'd', &end, 0)) == 0) { 156 errorflg = 1; 157 error(WARNING, "file %s:%d illegal end value\n", filename, line); 158 } else if (rv < 0) break; 159 if (Bgetfield(Bfd, 'd', &offset, 0) < 0) { 160 errorflg = 1; 161 error(WARNING, "file %s:%d illegal offset value\n", filename, line); 162 } 163 if ((rv=Bgetfield(Bfd, 's', psfontnam, 128)) == 0) { 164 errorflg = 1; 165 error(WARNING, "file %s:%d illegal fontname value\n", filename, line); 166 } else if (rv < 0) 167 break; 168 Brdline(Bfd, '\n'); 169 if (!errorflg) { 170 struct psfent *psfentp; 171 startfont = RUNEGETGROUP(start); 172 startchar = RUNEGETCHAR(start); 173 endfont = RUNEGETGROUP(end); 174 endchar = RUNEGETCHAR(end); 175 pfid = findpfn(psfontnam, 1); 176 if (startfont != endfont) { 177 error(WARNING, "font descriptions must not cross 256 glyph block boundary\n"); 178 break; 179 } 180 tp = &troffontab[trindex]; 181 tp->psfmap = galloc(tp->psfmap, ++tp->psfmapsize * 182 sizeof(struct psfent), 183 "readpsfontdesc():psfmap"); 184 psfentp = &(tp->psfmap[tp->psfmapsize-1]); 185 psfentp->start = start; 186 psfentp->end = end; 187 psfentp->offset = offset; 188 psfentp->psftid = pfid; 189 if (debug) { 190 fprint(2, "\tpsfmap->start=0x%x\n", start); 191 fprint(2, "\tpsfmap->end=0x%x\n", end); 192 fprint(2, "\tpsfmap->offset=0x%x\n", offset); 193 fprint(2, "\tpsfmap->pfid=0x%x\n", pfid); 194 } 195 SET(i); 196 USED(i, startchar, endchar); 197 /* 198 for (i=startchar; i<=endchar; i++) { 199 tp->charent[startfont][i].postfontid = pfid; 200 tp->charent[startfont][i].postcharid = i + offset - startchar; 201 } 202 */ 203 if (debug) { 204 fprint(2, "%x %x ", start, end); 205 if (offset) 206 fprint(2, "%x ", offset); 207 fprint(2, "%s\n", psfontnam); 208 } 209 line++; 210 } 211 } while(errorflg != 1); 212 Bterm(Bfd); 213 return(1); 214 } 215 216 int 217 readtroffmetric(char *fontname, int trindex) { 218 int ntoken, errorflg = 0, line = 1, rv; 219 int width, flag, charnum, thisfont, thischar; 220 char stoken[128], *str; 221 struct charent **cp; 222 BOOLEAN specharflag; 223 Biobuf *bfd; 224 Biobufhdr *Bfd; 225 Rune troffchar, quote; 226 static char *filename = 0; 227 228 if (debug) 229 fprint(2, "readtroffmetric(%s,%d)\n", fontname, trindex); 230 filename = galloc(filename, strlen(troffmetricdirname) + 4 + 231 strlen(devname) + 1 + strlen(fontname) + 1, 232 "readtroffmetric():filename"); 233 sprint(filename, "%s/dev%s/%s", troffmetricdirname, devname, fontname); 234 235 bfd = Bopen(filename, OREAD); 236 if (bfd == 0) { 237 error(WARNING, "cannot open file %s\n", filename); 238 return(0); 239 } 240 Bfd = &bfd->Biobufhdr; 241 do { 242 /* 243 * deal with the few lines at the beginning of the 244 * troff font metric files. 245 */ 246 if ((rv=Bgetfield(Bfd, 's', stoken, 128)) == 0) { 247 errorflg = 1; 248 error(WARNING, "file %s:%d illegal token\n", filename, line); 249 } else if (rv < 0) 250 break; 251 if (debug) 252 fprint(2, "%s\n", stoken); 253 254 if (strcmp(stoken, "name") == 0) { 255 if ((rv=Bgetfield(Bfd, 's', stoken, 128)) == 0) { 256 errorflg = 1; 257 error(WARNING, "file %s:%d illegal token\n", filename, line); 258 } else if (rv < 0) break; 259 } else if (strcmp(stoken, "named") == 0) { 260 Brdline(Bfd, '\n'); 261 } else if (strcmp(stoken, "fontname") == 0) { 262 if ((rv=Bgetfield(Bfd, 's', stoken, 128)) == 0) { 263 errorflg = 1; 264 error(WARNING, "file %s:%d illegal token\n", filename, line); 265 } else if (rv < 0) break; 266 } else if (strcmp(stoken, "spacewidth") == 0) { 267 if ((rv=Bgetfield(Bfd, 'd', &ntoken, 0)) == 0) { 268 errorflg = 1; 269 error(WARNING, "file %s:%d illegal token\n", filename, line); 270 } else if (rv < 0) break; 271 troffontab[trindex].spacewidth = ntoken; 272 thisfont = RUNEGETGROUP(' '); 273 thischar = RUNEGETCHAR(' '); 274 for (cp = &(troffontab[trindex].charent[thisfont][thischar]); *cp != 0; cp = &((*cp)->next)) 275 if ((*cp)->name) 276 if (strcmp((*cp)->name, " ") == 0) 277 break; 278 279 if (*cp == 0) *cp = galloc(0, sizeof(struct charent), "readtroffmetric:charent"); 280 (*cp)->postfontid = thisfont; 281 (*cp)->postcharid = thischar; 282 (*cp)->troffcharwidth = ntoken; 283 (*cp)->name = galloc(0, 2, "readtroffmetric: char name"); 284 (*cp)->next = 0; 285 strcpy((*cp)->name, " "); 286 } else if (strcmp(stoken, "special") == 0) { 287 troffontab[trindex].special = TRUE; 288 } else if (strcmp(stoken, "charset") == 0) { 289 line++; 290 break; 291 } 292 if (!errorflg) { 293 line++; 294 } 295 } while(!errorflg && rv>=0); 296 while(!errorflg && rv>=0) { 297 if ((rv=Bgetfield(Bfd, 's', stoken, 128)) == 0) { 298 errorflg = 1; 299 error(WARNING, "file %s:%d illegal rune token <0x%x> rv=%d\n", filename, line, troffchar, rv); 300 } else if (rv < 0) break; 301 if (utflen(stoken) > 1) specharflag = TRUE; 302 else specharflag = FALSE; 303 /* if this character is a quote we have to use the previous characters info */ 304 if ((rv=Bgetfield(Bfd, 'r', "e, 0)) == 0) { 305 errorflg = 1; 306 error(WARNING, "file %s:%d illegal width or quote token <0x%x> rv=%d\n", 307 filename, line, quote, rv); 308 } else if (rv < 0) break; 309 if (quote == '"') { 310 /* need some code here */ 311 goto flush; 312 } else 313 Bungetrune(Bfd); 314 315 if ((rv=Bgetfield(Bfd, 'd', &width, 0)) == 0) { 316 errorflg = 1; 317 error(WARNING, "file %s:%d illegal width token <0x%x> rv=%d\n", filename, line, troffchar, rv); 318 } else if (rv < 0) break; 319 if ((rv=Bgetfield(Bfd, 'd', &flag, 0)) == 0) { 320 errorflg = 1; 321 error(WARNING, "file %s:%d illegal flag token <0x%x> rv=%d\n", filename, line, troffchar, rv); 322 } else if (rv < 0) break; 323 if ((rv=Bgetfield(Bfd, 'd', &charnum, 0)) == 0) { 324 errorflg = 1; 325 error(WARNING, "file %s:%d illegal character number token <0x%x> rv=%d\n", filename, line, troffchar, rv); 326 } else if (rv < 0) 327 break; 328 flush: 329 str = Brdline(Bfd, '\n'); 330 /* stash the crap from the end of the line for debugging */ 331 if (debug) { 332 if (str == 0) { 333 fprint(2, "premature EOF\n"); 334 return(0); 335 } 336 str[Blinelen(Bfd)-1] = '\0'; 337 } 338 line++; 339 chartorune(&troffchar, stoken); 340 if (specharflag) 341 if (debug) 342 fprint(2, "%s %d %d 0x%x %s # special\n", 343 stoken, width, flag, charnum, str); 344 if (strcmp(stoken, "---") == 0) { 345 thisfont = RUNEGETGROUP(charnum); 346 thischar = RUNEGETCHAR(charnum); 347 stoken[0] = '\0'; 348 } else { 349 thisfont = RUNEGETGROUP(troffchar); 350 thischar = RUNEGETCHAR(troffchar); 351 } 352 for (cp = &troffontab[trindex].charent[thisfont][thischar]; 353 *cp != 0; cp = &(*cp)->next) 354 if ((*cp)->name) { 355 if (debug) 356 fprint(2, "installing <%s>, found <%s>\n", 357 stoken, (*cp)->name); 358 if (strcmp((*cp)->name, stoken) == 0) 359 break; 360 } 361 if (*cp == 0) 362 *cp = galloc(0, sizeof(struct charent), 363 "readtroffmetric:charent"); 364 (*cp)->postfontid = RUNEGETGROUP(charnum); 365 (*cp)->postcharid = RUNEGETCHAR(charnum); 366 (*cp)->troffcharwidth = width; 367 (*cp)->name = galloc(0, strlen(stoken)+1, "readtroffmetric: char name"); 368 (*cp)->next = 0; 369 strcpy((*cp)->name, stoken); 370 if (debug) { 371 if (specharflag) 372 fprint(2, "%s", stoken); 373 else 374 fprint(2, "%C", troffchar); 375 fprint(2, " %d %d 0x%x %s # psfontid=0x%x pscharid=0x%x thisfont=0x%x thischar=0x%x\n", 376 width, flag, charnum, str, 377 (*cp)->postfontid, 378 (*cp)->postcharid, 379 thisfont, thischar); 380 } 381 } 382 Bterm(Bfd); 383 Bflush(Bstderr); 384 return(1); 385 } 386 387 /* find index of troff font name in table 388 * returns -1 if name is not in table 389 * returns -2 if it cannot allocate memory 390 * returns -3 if there is a font mapping problem 391 * If insflg is not zero 392 * and the name is not found in the table, insert it. 393 */ 394 int 395 findtfn(char *fontname, BOOLEAN insflg) { 396 struct troffont *tp; 397 int i, j; 398 399 if (debug) 400 fprint(2, "findtfn(%s,%d)\n", fontname, insflg); 401 for (i=0; i<troffontcnt; i++) { 402 if (troffontab[i].trfontid==0) { 403 error(WARNING, "findtfn:troffontab[%d].trfontid=0x%x, botch!\n", 404 i, troffontab[i].trfontid); 405 continue; 406 } 407 if (strcmp(troffontab[i].trfontid, fontname) == 0) 408 return(i); 409 } 410 if (insflg) { 411 tp = (struct troffont *)galloc(troffontab, 412 sizeof(struct troffont)*(troffontcnt+1), 413 "findtfn: struct troffont:"); 414 if (tp == 0) 415 return(-2); 416 troffontab = tp; 417 tp = &(troffontab[troffontcnt]); 418 i = strlen(fontname); 419 tp->trfontid = galloc(0, i+1, "findtfn: trfontid:"); 420 421 /* initialize new troff font entry with name and numeric fields to 0 */ 422 strncpy(tp->trfontid, fontname, i); 423 tp->trfontid[i] = '\0'; 424 tp->special = FALSE; 425 tp->spacewidth = 0; 426 tp->psfmapsize = 0; 427 tp->psfmap = 0; 428 for (i=0; i<NUMOFONTS; i++) 429 for (j=0; j<FONTSIZE; j++) 430 tp->charent[i][j] = 0; 431 troffontcnt++; 432 if (!readtroffmetric(fontname, troffontcnt-1)) 433 return(-3); 434 if (!readpsfontdesc(fontname, troffontcnt-1)) 435 return(-3); 436 return(troffontcnt-1); 437 } 438 return(-1); 439 } 440 441 void 442 finish(void) { 443 int i; 444 445 Bprint(Bstdout, "%s", TRAILER); 446 Bprint(Bstdout, "done\n"); 447 Bprint(Bstdout, "%s", DOCUMENTFONTS); 448 449 for (i=0; i<pfnamcnt; i++) 450 if (pfnafontmtab[i].used) 451 Bprint(Bstdout, " %s", pfnafontmtab[i].str); 452 Bprint(Bstdout, "\n"); 453 454 Bprint(Bstdout, "%s %d\n", PAGES, pages_printed); 455 456 } 457 458 /* Set slant to n degrees. Disable slanting if n is 0. */ 459 void 460 t_slant(int n) { 461 fontslant = n; 462 curpostfontid = -1; 463 } 464 465 /* Set character height to n points. Disabled if n is 0 or the current size. */ 466 467 void 468 t_charht(int n) { 469 fontheight = (n == fontsize) ? 0 : n; 470 curpostfontid = -1; 471 } 472