| 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 } |