From 213fc4f6fb26bb5781ea3e489bf4cc5c2aca591e Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 17 Feb 2015 12:16:20 -0500 Subject: libdraw: autoscale fonts when moving between low and high dpi screens Change-Id: I6093955b222db89dfe437fb723593b173d888d01 Reviewed-on: https://plan9port-review.googlesource.com/1170 Reviewed-by: Russ Cox --- src/libdraw/buildfont.c | 18 +++++ src/libdraw/getsubfont.c | 19 +++--- src/libdraw/init.c | 12 ++++ src/libdraw/openfont.c | 165 ++++++++++++++++++++++++++++++++++++++++++---- src/libdraw/string.c | 2 +- src/libdraw/stringwidth.c | 2 +- src/libdraw/subfontname.c | 21 ++++-- 7 files changed, 212 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/libdraw/buildfont.c b/src/libdraw/buildfont.c index 0f14022e..512bc9d3 100644 --- a/src/libdraw/buildfont.c +++ b/src/libdraw/buildfont.c @@ -138,5 +138,23 @@ freefont(Font *f) free(f->cache); free(f->subf); free(f->sub); + + if(f->ondisplaylist) { + f->ondisplaylist = 0; + if(f->next) + f->next->prev = f->prev; + else + f->display->lastfont = f->prev; + if(f->prev) + f->prev->next = f->next; + else + f->display->firstfont = f->next; + } + + if(f->lodpi != f) + freefont(f->lodpi); + if(f->hidpi != f) + freefont(f->hidpi); + free(f); } diff --git a/src/libdraw/getsubfont.c b/src/libdraw/getsubfont.c index 3f3b6954..1a5006b4 100644 --- a/src/libdraw/getsubfont.c +++ b/src/libdraw/getsubfont.c @@ -11,17 +11,20 @@ int _fontpipe(char*); static void scalesubfont(Subfont*, int); Subfont* -_getsubfont(Display *d, Font *ff, char *name) +_getsubfont(Display *d, char *name) { int fd; Subfont *f; - - fd = open(name, OREAD); - if(fd < 0 && strncmp(name, "/mnt/font/", 10) == 0) - fd = _fontpipe(name+10); + int scale; + char *fname; + + scale = parsefontscale(name, &fname); + 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", name); + fprint(2, "getsubfont: can't open %s: %r\n", fname); return 0; } /* @@ -38,8 +41,8 @@ _getsubfont(Display *d, Font *ff, char *name) if(f == 0) fprint(2, "getsubfont: can't read %s: %r\n", name); close(fd); - if(ff->scale != 1 && ff->scale != 0) - scalesubfont(f, ff->scale); + if(scale > 1) + scalesubfont(f, scale); return f; } diff --git a/src/libdraw/init.c b/src/libdraw/init.c index b2df7fd7..452b6da7 100644 --- a/src/libdraw/init.c +++ b/src/libdraw/init.c @@ -199,6 +199,7 @@ int getwindow(Display *d, int ref) { Image *i, *oi; + Font *f; /* XXX check for destroyed? */ @@ -219,6 +220,17 @@ getwindow(Display *d, int ref) _freeimage1(screen); screen = _allocwindow(screen, _screen, i->r, ref, DWhite); d->screenimage = screen; + + + if(d->dpi >= DefaultDPI*3/2) { + for(f=d->firstfont; f != nil; f=f->next) + loadhidpi(f); + } else { + for(f=d->firstfont; f != nil; f=f->next) + if(f->lodpi != nil && f->lodpi != f) + swapfont(f, &f->hidpi, &f->lodpi); + } + return 0; } diff --git a/src/libdraw/openfont.c b/src/libdraw/openfont.c index ae1462d4..97102a22 100644 --- a/src/libdraw/openfont.c +++ b/src/libdraw/openfont.c @@ -5,23 +5,41 @@ extern vlong _drawflength(int); int _fontpipe(char*); +int +parsefontscale(char *name, char **base) +{ + char *p; + int scale; + + p = name; + scale = 0; + while('0' <= *p && *p <= '9') { + scale = scale*10 + *p - '0'; + p++; + } + if(*p == '*' && scale > 0) + *base = p+1; + else { + *base = name; + scale = 1; + } + return scale; +} + Font* -openfont(Display *d, char *name) +openfont1(Display *d, char *name) { Font *fnt; int fd, i, n, scale; - char *buf, *nambuf; + char *buf, *nambuf, *fname, *freename; nambuf = 0; - scale = 1; - if('1' <= name[0] && name[0] <= '9' && name[1] == '*') { - scale = name[0] - '0'; - name += 2; - } - fd = open(name, OREAD); + freename = nil; + scale = parsefontscale(name, &fname); - if(fd < 0 && strncmp(name, "/lib/font/bit/", 14) == 0){ - nambuf = smprint("#9/font/%s", name+14); + fd = open(fname, OREAD); + if(fd < 0 && strncmp(fname, "/lib/font/bit/", 14) == 0){ + nambuf = smprint("#9/font/%s", fname+14); if(nambuf == nil) return 0; nambuf = unsharp(nambuf); @@ -31,12 +49,18 @@ openfont(Display *d, char *name) free(nambuf); return 0; } - name = nambuf; + fname = nambuf; + if(scale > 1) { + name = smprint("%d*%s", scale, fname); + freename = name; + } else { + name = fname; + } } if(fd >= 0) n = _drawflength(fd); - if(fd < 0 && strncmp(name, "/mnt/font/", 10) == 0) { - fd = _fontpipe(name+10); + if(fd < 0 && strncmp(fname, "/mnt/font/", 10) == 0) { + fd = _fontpipe(fname+10); n = 8192; } if(fd < 0) @@ -59,6 +83,7 @@ openfont(Display *d, char *name) fnt = buildfont(d, buf, name); free(buf); free(nambuf); + free(freename); if(scale != 1) { fnt->scale = scale; fnt->height *= scale; @@ -68,6 +93,120 @@ openfont(Display *d, char *name) return fnt; } +void +swapfont(Font *targ, Font **oldp, Font **newp) +{ + Font f, *old, *new; + + if(targ != *oldp) + sysfatal("bad swapfont %p %p %p", targ, *oldp, *newp); + + old = *oldp; + new = *newp; + + f.name = old->name; + f.display = old->display; + f.height = old->height; + f.ascent = old->ascent; + f.width = old->width; + f.nsub = old->nsub; + f.age = old->age; + f.maxdepth = old->maxdepth; + f.ncache = old->ncache; + f.nsubf = old->nsubf; + f.scale = old->scale; + f.cache = old->cache; + f.subf = old->subf; + f.sub = old->sub; + f.cacheimage = old->cacheimage; + + old->name = new->name; + old->display = new->display; + old->height = new->height; + old->ascent = new->ascent; + old->width = new->width; + old->nsub = new->nsub; + old->age = new->age; + old->maxdepth = new->maxdepth; + old->ncache = new->ncache; + old->nsubf = new->nsubf; + old->scale = new->scale; + old->cache = new->cache; + old->subf = new->subf; + old->sub = new->sub; + old->cacheimage = new->cacheimage; + + new->name = f.name; + new->display = f.display; + new->height = f.height; + new->ascent = f.ascent; + new->width = f.width; + new->nsub = f.nsub; + new->age = f.age; + new->maxdepth = f.maxdepth; + new->ncache = f.ncache; + new->nsubf = f.nsubf; + new->scale = f.scale; + new->cache = f.cache; + new->subf = f.subf; + new->sub = f.sub; + new->cacheimage = f.cacheimage; + + *oldp = new; + *newp = old; +} + +void +loadhidpi(Font *f) +{ + char *name; + Font *fnew; + + if(f->hidpi == f) + return; + if(f->hidpi != nil) { + swapfont(f, &f->lodpi, &f->hidpi); + return; + } + + name = smprint("%d*%s", f->scale*2, f->name); + fnew = openfont1(f->display, name); + if(fnew == nil) + return; + f->hidpi = fnew; + free(name); + + swapfont(f, &f->lodpi, &f->hidpi); +} + +Font* +openfont(Display *d, char *name) +{ + Font *f; + + f = openfont1(d, name); + f->lodpi = f; + + /* add to display list for when dpi changes */ + /* d can be nil when invoked from mc. */ + if(d != nil) { + f->ondisplaylist = 1; + f->prev = d->lastfont; + f->next = nil; + if(f->prev) + f->prev->next = f; + else + d->firstfont = f; + d->lastfont = f; + + /* if this is a hi-dpi display, find hi-dpi version and swap */ + if(d->dpi >= DefaultDPI*3/2) + loadhidpi(f); + } + + return f; +} + int _fontpipe(char *name) { diff --git a/src/libdraw/string.c b/src/libdraw/string.c index c84112ec..392a7e8a 100644 --- a/src/libdraw/string.c +++ b/src/libdraw/string.c @@ -130,7 +130,7 @@ _string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, i } if(subfontname){ freesubfont(sf); - if((sf=_getsubfont(f->display, f, subfontname)) == 0){ + if((sf=_getsubfont(f->display, subfontname)) == 0){ def = f->display ? f->display->defaultfont : nil; if(def && f!=def) f = def; diff --git a/src/libdraw/stringwidth.c b/src/libdraw/stringwidth.c index e4630ca3..522fbc01 100644 --- a/src/libdraw/stringwidth.c +++ b/src/libdraw/stringwidth.c @@ -48,7 +48,7 @@ _stringnwidth(Font *f, char *s, Rune *r, int len) } if(subfontname){ freesubfont(sf); - if((sf=_getsubfont(f->display, f, subfontname)) == 0){ + if((sf=_getsubfont(f->display, subfontname)) == 0){ def = f->display ? f->display->defaultfont : nil; if(def && f!=def) f = def; diff --git a/src/libdraw/subfontname.c b/src/libdraw/subfontname.c index 874528be..9280244a 100644 --- a/src/libdraw/subfontname.c +++ b/src/libdraw/subfontname.c @@ -9,14 +9,16 @@ char* subfontname(char *cfname, char *fname, int maxdepth) { - char *t, *u, *tmp1, *tmp2; - int i; + char *t, *u, *tmp1, *tmp2, *base; + int i, scale; + + scale = parsefontscale(fname, &base); t = strdup(cfname); /* t is the return string */ if(strcmp(cfname, "*default*") == 0) return t; if(t[0] != '/'){ - tmp2 = strdup(fname); + tmp2 = strdup(base); u = utfrrune(tmp2, '/'); if(u) u[0] = 0; @@ -38,13 +40,24 @@ subfontname(char *cfname, char *fname, int maxdepth) tmp2 = smprint("%s.%d", t, i); if(access(tmp2, AREAD) == 0) { free(t); + if(scale > 1) { + t = smprint("%d*%s", scale, tmp2); + free(tmp2); + tmp2 = t; + } return tmp2; } } /* try default */ - if(strncmp(t, "/mnt/font/", 10) == 0 || access(t, AREAD) == 0) + if(strncmp(t, "/mnt/font/", 10) == 0 || access(t, AREAD) == 0) { + if(scale > 1) { + tmp2 = smprint("%d*%s", scale, t); + free(t); + t = tmp2; + } return t; + } return nil; } -- cgit v1.2.3