topenfont.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
topenfont.c (5560B) | |
--- | |
1 #include <u.h> | |
2 #include <libc.h> | |
3 #include <draw.h> | |
4 | |
5 extern vlong _drawflength(int); | |
6 int _fontpipe(char*); | |
7 | |
8 int | |
9 parsefontscale(char *name, char **base) | |
10 { | |
11 char *p; | |
12 int scale; | |
13 | |
14 p = name; | |
15 scale = 0; | |
16 while('0' <= *p && *p <= '9') { | |
17 scale = scale*10 + *p - '0'; | |
18 p++; | |
19 } | |
20 if(*p == '*' && scale > 0) | |
21 *base = p+1; | |
22 else { | |
23 *base = name; | |
24 scale = 1; | |
25 } | |
26 return scale; | |
27 } | |
28 | |
29 extern char _defontfile[]; | |
30 | |
31 Font* | |
32 openfont1(Display *d, char *name) | |
33 { | |
34 Font *fnt; | |
35 int fd, i, n, scale; | |
36 char *buf, *nambuf, *nambuf0, *fname, *freename; | |
37 | |
38 nambuf = 0; | |
39 freename = nil; | |
40 scale = parsefontscale(name, &fname); | |
41 | |
42 if(strcmp(fname, "*default*") == 0) { | |
43 buf = strdup(_defontfile); | |
44 goto build; | |
45 } | |
46 fd = open(fname, OREAD); | |
47 if(fd < 0 && strncmp(fname, "/lib/font/bit/", 14) == 0){ | |
48 nambuf = smprint("#9/font/%s", fname+14); | |
49 if(nambuf == nil) | |
50 return 0; | |
51 nambuf0 = unsharp(nambuf); | |
52 if(nambuf0 != nambuf) | |
53 free(nambuf); | |
54 nambuf = nambuf0; | |
55 if(nambuf == nil) | |
56 return 0; | |
57 if((fd = open(nambuf, OREAD)) < 0){ | |
58 free(nambuf); | |
59 return 0; | |
60 } | |
61 if(scale > 1) { | |
62 name = smprint("%d*%s", scale, nambuf); | |
63 freename = name; | |
64 } else { | |
65 name = nambuf; | |
66 } | |
67 } | |
68 if(fd >= 0) | |
69 n = _drawflength(fd); | |
70 if(fd < 0 && strncmp(fname, "/mnt/font/", 10) == 0) { | |
71 fd = _fontpipe(fname+10); | |
72 n = 1024*1024; | |
73 } | |
74 if(fd < 0){ | |
75 free(nambuf); | |
76 free(freename); | |
77 return 0; | |
78 } | |
79 | |
80 buf = malloc(n+1); | |
81 if(buf == 0){ | |
82 close(fd); | |
83 free(nambuf); | |
84 free(freename); | |
85 return 0; | |
86 } | |
87 i = readn(fd, buf, n); | |
88 close(fd); | |
89 if(i <= 0){ | |
90 free(buf); | |
91 free(nambuf); | |
92 free(freename); | |
93 return 0; | |
94 } | |
95 buf[i] = 0; | |
96 build: | |
97 fnt = buildfont(d, buf, name); | |
98 free(buf); | |
99 free(nambuf); | |
100 free(freename); | |
101 if(scale != 1) { | |
102 fnt->scale = scale; | |
103 fnt->height *= scale; | |
104 fnt->ascent *= scale; | |
105 fnt->width *= scale; | |
106 } | |
107 return fnt; | |
108 } | |
109 | |
110 void | |
111 swapfont(Font *targ, Font **oldp, Font **newp) | |
112 { | |
113 Font f, *old, *new; | |
114 | |
115 if(targ != *oldp) | |
116 sysfatal("bad swapfont %p %p %p", targ, *oldp, *newp); | |
117 | |
118 old = *oldp; | |
119 new = *newp; | |
120 | |
121 f.name = old->name; | |
122 f.display = old->display; | |
123 f.height = old->height; | |
124 f.ascent = old->ascent; | |
125 f.width = old->width; | |
126 f.nsub = old->nsub; | |
127 f.age = old->age; | |
128 f.maxdepth = old->maxdepth; | |
129 f.ncache = old->ncache; | |
130 f.nsubf = old->nsubf; | |
131 f.scale = old->scale; | |
132 f.cache = old->cache; | |
133 f.subf = old->subf; | |
134 f.sub = old->sub; | |
135 f.cacheimage = old->cacheimage; | |
136 | |
137 old->name = new->name; | |
138 old->display = new->display; | |
139 old->height = new->height; | |
140 old->ascent = new->ascent; | |
141 old->width = new->width; | |
142 old->nsub = new->nsub; | |
143 old->age = new->age; | |
144 old->maxdepth = new->maxdepth; | |
145 old->ncache = new->ncache; | |
146 old->nsubf = new->nsubf; | |
147 old->scale = new->scale; | |
148 old->cache = new->cache; | |
149 old->subf = new->subf; | |
150 old->sub = new->sub; | |
151 old->cacheimage = new->cacheimage; | |
152 | |
153 new->name = f.name; | |
154 new->display = f.display; | |
155 new->height = f.height; | |
156 new->ascent = f.ascent; | |
157 new->width = f.width; | |
158 new->nsub = f.nsub; | |
159 new->age = f.age; | |
160 new->maxdepth = f.maxdepth; | |
161 new->ncache = f.ncache; | |
162 new->nsubf = f.nsubf; | |
163 new->scale = f.scale; | |
164 new->cache = f.cache; | |
165 new->subf = f.subf; | |
166 new->sub = f.sub; | |
167 new->cacheimage = f.cacheimage; | |
168 | |
169 *oldp = new; | |
170 *newp = old; | |
171 } | |
172 | |
173 static char* | |
174 hidpiname(Font *f) | |
175 { | |
176 char *p, *q; | |
177 int size; | |
178 | |
179 // If font name has form x,y return y. | |
180 p = strchr(f->namespec, ','); | |
181 if(p != nil) | |
182 return strdup(p+1); | |
183 | |
184 // If font name is /mnt/font/Name/Size/font, scale Size. | |
185 if(strncmp(f->name, "/mnt/font/", 10) == 0) { | |
186 p = strchr(f->name+10, '/'); | |
187 if(p == nil || *++p < '0' || *p > '9') | |
188 goto scale; | |
189 q = p; | |
190 size = 0; | |
191 while('0' <= *q && *q <= '9') | |
192 size = size*10 + *q++ - '0'; | |
193 return smprint("%.*s%d%s", utfnlen(f->name, p-f->name), … | |
194 } | |
195 | |
196 // Otherwise use pixel doubling. | |
197 scale: | |
198 return smprint("%d*%s", f->scale*2, f->name); | |
199 } | |
200 | |
201 void | |
202 loadhidpi(Font *f) | |
203 { | |
204 char *name; | |
205 Font *fnew; | |
206 | |
207 if(f->hidpi == f) | |
208 return; | |
209 if(f->hidpi != nil) { | |
210 swapfont(f, &f->lodpi, &f->hidpi); | |
211 return; | |
212 } | |
213 | |
214 name = hidpiname(f); | |
215 fnew = openfont1(f->display, name); | |
216 if(fnew == nil) | |
217 return; | |
218 f->hidpi = fnew; | |
219 free(name); | |
220 | |
221 swapfont(f, &f->lodpi, &f->hidpi); | |
222 } | |
223 | |
224 Font* | |
225 openfont(Display *d, char *name) | |
226 { | |
227 Font *f; | |
228 char *p; | |
229 char *namespec; | |
230 | |
231 // If font name has form x,y use x for lodpi, y for hidpi. | |
232 name = strdup(name); | |
233 namespec = strdup(name); | |
234 if((p = strchr(name, ',')) != nil) | |
235 *p = '\0'; | |
236 | |
237 f = openfont1(d, name); | |
238 if(!f) | |
239 return nil; | |
240 f->lodpi = f; | |
241 free(f->namespec); | |
242 f->namespec = namespec; | |
243 | |
244 /* add to display list for when dpi changes */ | |
245 /* d can be nil when invoked from mc. */ | |
246 if(d != nil) { | |
247 f->ondisplaylist = 1; | |
248 f->prev = d->lastfont; | |
249 f->next = nil; | |
250 if(f->prev) | |
251 f->prev->next = f; | |
252 else | |
253 d->firstfont = f; | |
254 d->lastfont = f; | |
255 | |
256 /* if this is a hi-dpi display, find hi-dpi version and … | |
257 if(d->dpi >= DefaultDPI*3/2) | |
258 loadhidpi(f); | |
259 } | |
260 | |
261 free(name); | |
262 | |
263 return f; | |
264 } | |
265 | |
266 int | |
267 _fontpipe(char *name) | |
268 { | |
269 int p[2]; | |
270 char c; | |
271 char buf[1024], *argv[10]; | |
272 int nbuf, pid; | |
273 | |
274 if(pipe(p) < 0) | |
275 return -1; | |
276 pid = rfork(RFNOWAIT|RFFDG|RFPROC); | |
277 if(pid < 0) { | |
278 close(p[0]); | |
279 close(p[1]); | |
280 return -1; | |
281 } | |
282 if(pid == 0) { | |
283 close(p[0]); | |
284 dup(p[1], 1); | |
285 dup(p[1], 2); | |
286 if(p[1] > 2) | |
287 close(p[1]); | |
288 argv[0] = "fontsrv"; | |
289 argv[1] = "-pp"; | |
290 argv[2] = name; | |
291 argv[3] = nil; | |
292 execvp("fontsrv", argv); | |
293 print("exec fontsrv: %r\n"); | |
294 _exit(0); | |
295 } | |
296 close(p[1]); | |
297 | |
298 // success marked with leading \001. | |
299 // otherwise an error happened. | |
300 for(nbuf=0; nbuf<sizeof buf-1; nbuf++) { | |
301 if(read(p[0], &c, 1) < 1 || c == '\n') { | |
302 buf[nbuf] = '\0'; | |
303 werrstr(buf); | |
304 close(p[0]); | |
305 return -1; | |
306 } | |
307 if(c == '\001') | |
308 break; | |
309 } | |
310 return p[0]; | |
311 } |