aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/draw.h17
-rw-r--r--man/man3/graphics.315
-rw-r--r--src/libdraw/buildfont.c18
-rw-r--r--src/libdraw/getsubfont.c19
-rw-r--r--src/libdraw/init.c12
-rw-r--r--src/libdraw/openfont.c165
-rw-r--r--src/libdraw/string.c2
-rw-r--r--src/libdraw/stringwidth.c2
-rw-r--r--src/libdraw/subfontname.c21
9 files changed, 243 insertions, 28 deletions
diff --git a/include/draw.h b/include/draw.h
index ff760dd7..329108d9 100644
--- a/include/draw.h
+++ b/include/draw.h
@@ -206,6 +206,9 @@ struct Display
struct Mux *mux;
int srvfd;
int dpi;
+
+ Font *firstfont;
+ Font *lastfont;
};
struct Image
@@ -319,6 +322,15 @@ struct Font
Cachesubf *subf;
Cachefont **sub; /* as read from file */
Image *cacheimage;
+
+ /* doubly linked list of fonts known to display */
+ int ondisplaylist;
+ Font *next;
+ Font *prev;
+
+ /* on hi-dpi systems, one of these is set to f and the other is the other-dpi version of f */
+ Font *lodpi;
+ Font *hidpi;
};
#define Dx(r) ((r).max.x-(r).min.x)
@@ -460,6 +472,7 @@ extern void borderop(Image*, Rectangle, int, Image*, Point, Drawop);
* Font management
*/
extern Font* openfont(Display*, char*);
+extern int parsefontscale(char*, char**);
extern Font* buildfont(Display*, char*, char*);
extern void freefont(Font*);
extern Font* mkfont(Subfont*, Rune);
@@ -483,11 +496,13 @@ extern int runestringnwidth(Font*, Rune*, int);
extern Point strsubfontwidth(Subfont*, char*);
extern int loadchar(Font*, Rune, Cacheinfo*, int, int, char**);
extern char* subfontname(char*, char*, int);
-extern Subfont* _getsubfont(Display*, Font*, char*);
+extern Subfont* _getsubfont(Display*, char*);
extern Subfont* getdefont(Display*);
extern void lockdisplay(Display*);
extern void unlockdisplay(Display*);
extern int drawlsetrefresh(u32int, int, void*, void*);
+extern void loadhidpi(Font*);
+extern void swapfont(Font*, Font**, Font**);
/*
* Predefined
diff --git a/man/man3/graphics.3 b/man/man3/graphics.3
index d07c269a..43214f1f 100644
--- a/man/man3/graphics.3
+++ b/man/man3/graphics.3
@@ -487,6 +487,21 @@ point to the portion of the window inside the border;
sophisticated clients may use
.B _screen
to make further subwindows.
+If
+.I getwindow
+is being called due to a resizing of the window,
+the resize may be accompanied by a change in screen pixel density (DPI),
+in which case the value of the
+.BR Display 's
+.B dpi
+field and any open
+.BR Font 's
+.B height
+and
+.B ascent
+fields may be updated during the call to
+.IR getwindow .
+Programs should discard any cached information about display or font sizes.
.\" Programs desiring multiple independent windows
.\" may use the mechanisms of
.\" .IR rio (4)
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;
}