URI:
       tfont.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tfont.c (8658B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <draw.h>
            4 #include <event.h>
            5 #include <bio.h>
            6 #include "proof.h"
            7 
            8 char        fname[NFONT][20];                /* font names */
            9 char lastload[NFONT][20];        /* last file name prefix loaded for this font */
           10 Font        *fonttab[NFONT][NSIZE];        /* pointers to fonts */
           11 int        fmap[NFONT];                /* what map to use with this font */
           12 
           13 static void        loadfont(int, int);
           14 static void        fontlookup(int, char *);
           15 static void        buildxheight(Biobuf*);
           16 static void        buildmap(Biobuf*);
           17 static void        buildtroff(char *);
           18 static void        addmap(int, char *, int);
           19 static char        *map(Rune*, int);
           20 static void        scanstr(char *, char *, char **);
           21 
           22 int        specfont;        /* somehow, number of special font */
           23 
           24 #define        NMAP        5
           25 #define        QUICK        2048        /* char values less than this are quick to look up */
           26 #define        eq(s,t)        strcmp((char *) s, (char *) t) == 0
           27 
           28 int        curmap        = -1;        /* what map are we working on */
           29 
           30 typedef struct Link Link;
           31 struct Link        /* link names together */
           32 {
           33         uchar        *name;
           34         int        val;
           35         Link        *next;
           36 };
           37 
           38 typedef struct Map Map;
           39 struct Map        /* holds a mapping from uchar name to index */
           40 {
           41         double        xheight;
           42         Rune        quick[QUICK];        /* low values get special treatment */
           43         Link        *slow;        /* other stuff goes into a link list */
           44 };
           45 
           46 Map        charmap[5];
           47 
           48 typedef struct Fontmap Fontmap;
           49 struct Fontmap        /* mapping from troff name to filename */
           50 {
           51         char        *troffname;
           52         char        *prefix;
           53         int        map;                /* which charmap to use for this font */
           54         char        *fallback;        /* font to look in if can't find char here */
           55 };
           56 
           57 Fontmap        fontmap[100];
           58 int        pos2fontmap[NFONT];        /* indexed by troff font position, gives Fontmap */
           59 int        nfontmap        = 0;        /* how many are there */
           60 
           61 
           62 void
           63 dochar(Rune r[])
           64 {
           65         char *s, *fb;
           66         Font *f;
           67         Point p;
           68         int fontno, fm, i;
           69         char buf[10];
           70 
           71         fontno = curfont;
           72         if((s = map(r, curfont)) == 0){                /* not on current font */
           73                 if ((s = map(r, specfont)) != 0)        /* on special font */
           74                         fontno = specfont;
           75                 else{
           76                         /* look for fallback */
           77                         fm = pos2fontmap[curfont];
           78                         fb = fontmap[fm].fallback;
           79                         if(fb){
           80                                 /* see if fallback is mounted */
           81                                 for(i = 0; i < NFONT; i++){
           82                                         if(eq(fb, fontmap[pos2fontmap[i]].troffname)){
           83                                                 s = map(r, i);
           84                                                 if(s){
           85                                                         fontno = i;
           86                                                         goto found;
           87                                                 }
           88                                         }
           89                                 }
           90                         }
           91                         /* no such char; use name itself on defont */
           92                         /* this is not a general solution */
           93                         p.x = hpos/DIV + xyoffset.x + offset.x;
           94                         p.y = vpos/DIV + xyoffset.y + offset.y;
           95                         p.y -= font->ascent;
           96                         sprint(buf, "%S", r);
           97                         string(screen, p, display->black, ZP, font, buf);
           98                         return;
           99                 }
          100         }
          101     found:
          102         p.x = hpos/DIV + xyoffset.x + offset.x;
          103         p.y = vpos/DIV + xyoffset.y + offset.y;
          104         while ((f = fonttab[fontno][cursize]) == 0)
          105                 loadfont(fontno, cursize);
          106         p.y -= f->ascent;
          107         dprint(2, "putting %S at %d,%d font %d, size %d\n", r, p.x, p.y, fontno, cursize);
          108         string(screen, p, display->black, ZP, f, s);
          109 }
          110 
          111 static int drawlog2[] = {
          112         0, 0,
          113         1, 1,
          114         2, 2, 2, 2,
          115         3, 3, 3, 3, 3, 3, 3, 3,
          116         4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
          117         5
          118 };
          119 
          120 static void
          121 loadfont(int n, int s)
          122 {
          123         char file[100];
          124         int i, fd, t, deep;
          125         static char *try[3] = {"", "times/R.", "pelm/"};
          126         Subfont *f;
          127         Font *ff;
          128 
          129         try[0] = fname[n];
          130         dprint(2, "loadfont %d %d\n", n, s);
          131         for (t = 0; t < 3; t++){
          132                 i = s * mag * charmap[fmap[n]].xheight/0.72;        /* a pixel is 0.72 points */
          133                 if (i < MINSIZE)
          134                         i = MINSIZE;
          135                 dprint(2, "size %d, i %d, mag %g\n", s, i, mag);
          136                 for(; i >= MINSIZE; i--){
          137                         /* if .font file exists, take that */
          138                         sprint(file, "%s/%s%d.font", libfont, try[t], i);
          139                         ff = openfont(display, file);
          140                         if(ff != 0){
          141                                 fonttab[n][s] = ff;
          142                                 dprint(2, "using %s for font %d %d\n", file, n, s);
          143                                 return;
          144                         }
          145                         /* else look for a subfont file */
          146                         for (deep = drawlog2[screen->depth]; deep >= 0; deep--){
          147                                 sprint(file, "%s/%s%d.%d", libfont, try[t], i, deep);
          148                                 dprint(2, "trying %s for %d\n", file, i);
          149                                 if ((fd = open(file, 0)) >= 0){
          150                                         f = readsubfont(display, file, fd, 0);
          151                                         if (f == 0) {
          152                                                 fprint(2, "can't rdsubfontfile %s: %r\n", file);
          153                                                 exits("rdsubfont");
          154                                         }
          155                                         close(fd);
          156                                         ff = mkfont(f, 0);
          157                                         if(ff == 0){
          158                                                 fprint(2, "can't mkfont %s: %r\n", file);
          159                                                 exits("rdsubfont");
          160                                         }
          161                                         fonttab[n][s] = ff;
          162                                         dprint(2, "using %s for font %d %d\n", file, n, s);
          163                                         return;
          164                                 }
          165                         }
          166                 }
          167         }
          168         fprint(2, "can't find font %s.%d or substitute, quitting\n", fname[n], s);
          169         exits("no font");
          170 }
          171 
          172 void
          173 loadfontname(int n, char *s)
          174 {
          175         int i;
          176         Font *f, *g = 0;
          177 
          178         if (strcmp(s, fname[n]) == 0)
          179                 return;
          180         if(fname[n] && fname[n][0]){
          181                 if(lastload[n] && strcmp(lastload[n], fname[n]) == 0)
          182                         return;
          183                 strcpy(lastload[n], fname[n]);
          184         }
          185         fontlookup(n, s);
          186         for (i = 0; i < NSIZE; i++)
          187                 if (f = fonttab[n][i]){
          188                         if (f != g) {
          189                                 freefont(f);
          190                                 g = f;
          191                         }
          192                         fonttab[n][i] = 0;
          193                 }
          194 }
          195 
          196 void
          197 allfree(void)
          198 {
          199         int i;
          200 
          201         for (i=0; i<NFONT; i++)
          202                 loadfontname(i, "??");
          203 }
          204 
          205 
          206 void
          207 readmapfile(char *file)
          208 {
          209         Biobuf *fp;
          210         char *p, cmd[100];
          211 
          212         if ((fp=Bopen(file, OREAD)) == 0){
          213                 fprint(2, "proof: can't open map file %s\n", file);
          214                 exits("urk");
          215         }
          216         while((p=Brdline(fp, '\n')) != 0) {
          217                 p[Blinelen(fp)-1] = 0;
          218                 scanstr(p, cmd, 0);
          219                 if(p[0]=='\0' || eq(cmd, "#"))        /* skip comments, empty */
          220                         continue;
          221                 else if(eq(cmd, "xheight"))
          222                         buildxheight(fp);
          223                 else if(eq(cmd, "map"))
          224                         buildmap(fp);
          225                 else if(eq(cmd, "special"))
          226                         buildtroff(p);
          227                 else if(eq(cmd, "troff"))
          228                         buildtroff(p);
          229                 else
          230                         fprint(2, "weird map line %s\n", p);
          231         }
          232         Bterm(fp);
          233 }
          234 
          235 static void
          236 buildxheight(Biobuf *fp)        /* map goes from char name to value to print via *string() */
          237 {
          238         char *line;
          239 
          240         line = Brdline(fp, '\n');
          241         if(line == 0){
          242                 fprint(2, "proof: bad map file\n");
          243                 exits("map");
          244         }
          245         charmap[curmap].xheight = atof(line);
          246 }
          247 
          248 static void
          249 buildmap(Biobuf *fp)        /* map goes from char name to value to print via *string() */
          250 {
          251         uchar *p, *line, ch[100];
          252         int val;
          253         Rune r;
          254 
          255         curmap++;
          256         if(curmap >= NMAP){
          257                 fprint(2, "proof: out of char maps; recompile\n");
          258                 exits("charmap");
          259         }
          260         while ((line = Brdline(fp, '\n'))!= 0){
          261                 if (line[0] == '\n')
          262                         return;
          263                 line[Blinelen(fp)-1] = 0;
          264                 scanstr((char *) line, (char *) ch, (char **)(void*)&p);
          265                 if (ch[0] == '\0') {
          266                         fprint(2, "bad map file line '%s'\n", (char*)line);
          267                         continue;
          268                 }
          269                 val = strtol((char *) p, 0, 10);
          270 dprint(2, "buildmap %s (%x %x) %s %d\n", (char*)ch, ch[0], ch[1], (char*)p, val);
          271                 chartorune(&r, (char*)ch);
          272                 if(utflen((char*)ch)==1 && r<QUICK)
          273                         charmap[curmap].quick[r] = val;
          274                 else
          275                         addmap(curmap, strdup((char *) ch), val);        /* put somewhere else */
          276         }
          277 }
          278 
          279 static void
          280 addmap(int n, char *s, int val)        /* stick a new link on */
          281 {
          282         Link *p = (Link *) malloc(sizeof(Link));
          283         Link *prev = charmap[n].slow;
          284 
          285         if(p == 0)
          286                 exits("out of memory in addmap");
          287         p->name = (uchar *) s;
          288         p->val = val;
          289         p->next = prev;
          290         charmap[n].slow = p;
          291 }
          292 
          293 static void
          294 buildtroff(char *buf)        /* map troff names into bitmap filenames */
          295 {                                /* e.g., R -> times/R., I -> times/I., etc. */
          296         char *p, cmd[100], name[200], prefix[400], fallback[100];
          297 
          298         scanstr(buf, cmd, &p);
          299         scanstr(p, name, &p);
          300         scanstr(p, prefix, &p);
          301         while(*p!=0 && isspace(*p))
          302                 p++;
          303         if(*p != 0){
          304                 scanstr(p, fallback, &p);
          305                 fontmap[nfontmap].fallback = strdup(fallback);
          306         }else
          307                 fontmap[nfontmap].fallback = 0;
          308         fontmap[nfontmap].troffname = strdup(name);
          309         fontmap[nfontmap].prefix = strdup(prefix);
          310         fontmap[nfontmap].map = curmap;
          311         dprint(2, "troff name %s is bitmap %s map %d in slot %d fallback %s\n", name, prefix, curmap, nfontmap, fontmap[nfontmap].fallback? fontmap[nfontmap].fallback : "<null>");
          312         nfontmap++;
          313 }
          314 
          315 static void
          316 fontlookup(int n, char *s)        /* map troff name of s into position n */
          317 {
          318         int i;
          319 
          320         for(i = 0; i < nfontmap; i++)
          321                 if (eq(s, fontmap[i].troffname)) {
          322                         strcpy(fname[n], fontmap[i].prefix);
          323                         fmap[n] = fontmap[i].map;
          324                         pos2fontmap[n] = i;
          325                         if (eq(s, "S"))
          326                                 specfont = n;
          327                         dprint(2, "font %d %s is %s\n", n, s, fname[n]);
          328                         return;
          329                 }
          330         /* god help us if this font isn't there */
          331 }
          332 
          333 
          334 static char *
          335 map(Rune rp[], int font)        /* figure out mapping for char in this font */
          336 {
          337         static char s[100];
          338         char c[10];
          339         Link *p;
          340         Rune r;
          341 
          342         if(rp[1]==0 &&  rp[0]<QUICK)        /* fast lookup */
          343                 r = charmap[fmap[font]].quick[rp[0]];
          344         else {        /* high-valued or compound character name */
          345                 sprint(c, "%S", rp);
          346                 r = 0;
          347                 for (p = charmap[fmap[font]].slow; p; p = p->next)
          348                         if(eq(c, p->name)){
          349                                 r = p->val;
          350                                 break;
          351                         }
          352         }
          353         if(r == 0){        /* not there */
          354                 dprint(2, "didn't find %S font# %d\n", rp, font);
          355                 return 0;
          356         }
          357         dprint(2, "map %S to %s font# %d\n", rp, s, font);
          358         s[runetochar(s, &r)] = 0;
          359         return s;
          360 }
          361 
          362 static void
          363 scanstr(char *s, char *ans, char **ep)
          364 {
          365         for (; isspace((uchar) *s); s++)
          366                 ;
          367         for (; *s!=0 && !isspace((uchar) *s); )
          368                 *ans++ = *s++;
          369         *ans = 0;
          370         if (ep)
          371                 *ep = s;
          372 }