plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }