aboutsummaryrefslogtreecommitdiff
path: root/src/libdraw/openfont.c
blob: ae1462d41e344a6a668685e3d34b26fdd21aee15 (plain)
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
#include <u.h>
#include <libc.h>
#include <draw.h>

extern vlong _drawflength(int);
int _fontpipe(char*);

Font*
openfont(Display *d, char *name)
{
	Font *fnt;
	int fd, i, n, scale;
	char *buf, *nambuf;

	nambuf = 0;
	scale = 1;
	if('1' <= name[0] && name[0] <= '9' && name[1] == '*') {
		scale = name[0] - '0';
		name += 2;
	}
	fd = open(name, OREAD);

	if(fd < 0 && strncmp(name, "/lib/font/bit/", 14) == 0){
		nambuf = smprint("#9/font/%s", name+14);
		if(nambuf == nil)
			return 0;
		nambuf = unsharp(nambuf);
		if(nambuf == nil)
			return 0;
		if((fd = open(nambuf, OREAD)) < 0){
			free(nambuf);
			return 0;
		}
		name = nambuf;
	}
	if(fd >= 0)
		n = _drawflength(fd);
	if(fd < 0 && strncmp(name, "/mnt/font/", 10) == 0) {
		fd = _fontpipe(name+10);
		n = 8192;
	}
	if(fd < 0)
		return 0;

	buf = malloc(n+1);
	if(buf == 0){
		close(fd);
		free(nambuf);
		return 0;
	}
	i = readn(fd, buf, n);
	close(fd);
	if(i <= 0){
		free(buf);
		free(nambuf);
		return 0;
	}
	buf[i] = 0;
	fnt = buildfont(d, buf, name);
	free(buf);
	free(nambuf);
	if(scale != 1) {
		fnt->scale = scale;
		fnt->height *= scale;
		fnt->ascent *= scale;
		fnt->width *= scale;
	}
	return fnt;
}

int
_fontpipe(char *name)
{
	int p[2];
	char c;
	char buf[1024], *argv[10];
	int nbuf, pid;
	
	if(pipe(p) < 0)
		return -1;
	pid = rfork(RFNOWAIT|RFFDG|RFPROC);
	if(pid < 0) {
		close(p[0]);
		close(p[1]);
		return -1;
	}
	if(pid == 0) {
		close(p[0]);
		dup(p[1], 1);
		dup(p[1], 2);
		if(p[1] > 2)
			close(p[1]);
		argv[0] = "fontsrv";
		argv[1] = "-pp";
		argv[2] = name;
		argv[3] = nil;
		execvp("fontsrv", argv);
		print("exec fontsrv: %r\n");
		_exit(0);
	}
	close(p[1]);
	
	// success marked with leading \001.
	// otherwise an error happened.
	for(nbuf=0; nbuf<sizeof buf-1; nbuf++) {
		if(read(p[0], &c, 1) < 1 || c == '\n') {
			buf[nbuf] = '\0';
			werrstr(buf);
			close(p[0]);
			return -1;
		}
		if(c == '\001')
			break;
	}
	return p[0];
}