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 <rsc@swtch.com>
This commit is contained in:
Russ Cox 2015-02-17 12:16:20 -05:00
parent 77f23268f7
commit 213fc4f6fb
9 changed files with 243 additions and 28 deletions

View file

@ -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);
}

View file

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

View file

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

View file

@ -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)
{

View file

@ -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;

View file

@ -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;

View file

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