getsubfont.c (3077B)
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 }