Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include "defont.h"
6 /*
7 * Default version: treat as file name
8 */
10 int _fontpipe(char*);
11 static int defaultpipe(void);
13 static void scalesubfont(Subfont*, int);
15 Subfont*
16 _getsubfont(Display *d, char *name)
17 {
18 int fd;
19 Subfont *f;
20 int scale;
21 char *fname;
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 }
53 static int
54 defaultpipe(void)
55 {
56 int p[2], pid;
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 }
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;
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;
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);
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);
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);
120 freeimage(f->bits);
121 f->bits = i;
122 f->height *= scale;
123 f->ascent *= scale;
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;