URI:
       tgetsubfont.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
       ---
       tgetsubfont.c (3076B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <draw.h>
            4 #include "defont.h"
            5 
            6 /*
            7  * Default version: treat as file name
            8  */
            9 
           10 int _fontpipe(char*);
           11 static int defaultpipe(void);
           12 
           13 static void scalesubfont(Subfont*, int);
           14 
           15 Subfont*
           16 _getsubfont(Display *d, char *name)
           17 {
           18         int fd;
           19         Subfont *f;
           20         int scale;
           21         char *fname;
           22 
           23         scale = parsefontscale(name, &fname);
           24         if(strcmp(fname, "*default*") == 0)
           25                 fd = defaultpipe();
           26         else
           27                 fd = open(fname, OREAD);
           28         if(fd < 0 && strncmp(fname, "/mnt/font/", 10) == 0)
           29                 fd = _fontpipe(fname+10);
           30         if(fd < 0){
           31                 fprint(2, "getsubfont: can't open %s: %r\n", fname);
           32                 return 0;
           33         }
           34         /*
           35          * unlock display so i/o happens with display released, unless
           36          * user is doing his own locking, in which case this could break things.
           37          * _getsubfont is called only from string.c and stringwidth.c,
           38          * which are known to be safe to have this done.
           39          */
           40         if(d && d->locking == 0)
           41                 unlockdisplay(d);
           42         f = readsubfont(d, name, fd, d && d->locking==0);
           43         if(d && d->locking == 0)
           44                 lockdisplay(d);
           45         if(f == 0)
           46                 fprint(2, "getsubfont: can't read %s: %r\n", name);
           47         close(fd);
           48         if(scale > 1)
           49                 scalesubfont(f, scale);
           50         return f;
           51 }
           52 
           53 static int
           54 defaultpipe(void)
           55 {
           56         int p[2], pid;
           57 
           58         // Used to assume that defontdata (<5k) fit in the
           59         // pipe buffer, especially since p9pipe is actually
           60         // a socket pair. But OpenBSD in particular saw hangs,
           61         // so feed the pipe it the "right" way with a subprocess.
           62         if(pipe(p) < 0)
           63                 return -1;
           64         if((pid = fork()) < 0) {
           65                 close(p[0]);
           66                 close(p[1]);
           67                 return -1;
           68         }
           69         if(pid == 0) {
           70                 close(p[0]);
           71                 write(p[1], defontdata, sizeof defontdata);
           72                 close(p[1]);
           73                 _exit(0);
           74         }
           75         return p[0];
           76 }
           77 
           78 static void
           79 scalesubfont(Subfont *f, int scale)
           80 {
           81         Image *i;
           82         Rectangle r, r2;
           83         int y, x, x2, j;
           84         uchar *src, *dst;
           85         int srcn, dstn, n, mask, v, pack;
           86 
           87         r = f->bits->r;
           88         r2 = r;
           89         r2.min.x *= scale;
           90         r2.min.y *= scale;
           91         r2.max.x *= scale;
           92         r2.max.y *= scale;
           93 
           94         srcn = bytesperline(r, f->bits->depth);
           95         src = malloc(srcn);
           96         dstn = bytesperline(r2, f->bits->depth);
           97         dst = malloc(dstn+1);
           98         i = allocimage(f->bits->display, r2, f->bits->chan, 0, DBlack);
           99         for(y=r.min.y; y < r.max.y; y++) {
          100                 n = unloadimage(f->bits, Rect(r.min.x, y, r.max.x, y+1), src, srcn);
          101                 if(n != srcn) {
          102                         abort();
          103                         sysfatal("scalesubfont: bad unload %R %R: %d < %d: %r", f->bits->r, Rect(r.min.x, y, r.max.x, y+1), n, srcn);
          104                 }
          105                 memset(dst, 0, dstn+1);
          106                 pack = 8 / f->bits->depth;
          107                 mask = (1<<f->bits->depth) - 1;
          108                 for(x=0; x<Dx(r); x++) {
          109                         v = ((src[x/pack] << ((x%pack)*f->bits->depth)) >> (8 - f->bits->depth)) & mask;
          110                         for(j=0; j<scale; j++) {
          111                                 x2 = x*scale+j;
          112                                 dst[x2/pack] |= v << (8 - f->bits->depth) >> ((x2%pack)*f->bits->depth);
          113                         }
          114                 }
          115                 if(dst[dstn] != 0)
          116                         sysfatal("overflow dst");
          117                 for(j=0; j<scale; j++)
          118                         loadimage(i, Rect(r2.min.x, y*scale+j, r2.max.x, y*scale+j+1), dst, dstn);
          119         }
          120         freeimage(f->bits);
          121         f->bits = i;
          122         f->height *= scale;
          123         f->ascent *= scale;
          124 
          125         for(j=0; j<f->n; j++) {
          126                 f->info[j].x *= scale;
          127                 f->info[j].top *= scale;
          128                 f->info[j].bottom *= scale;
          129                 f->info[j].left *= scale;
          130                 f->info[j].width *= scale;
          131         }
          132 }