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