libdraw: add 2*font syntax for scaled fonts An experiment. Change-Id: I40660a211b8372701597d80f7e86917e94cccbaa Reviewed-on: https://plan9port-review.googlesource.com/1161 Reviewed-by: Russ Cox <rsc@swtch.com>
diff --git a/include/draw.h b/include/draw.h index d5f2ca6..ff760dd 100644 --- a/include/draw.h +++ b/include/draw.h
@@ -314,6 +314,7 @@ int maxdepth; /* maximum depth of all loaded subfonts */ int ncache; /* size of cache */ int nsubf; /* size of subfont list */ + int scale; /* pixel scaling to apply */ Cacheinfo *cache; Cachesubf *subf; Cachefont **sub; /* as read from file */ @@ -482,7 +483,7 @@ extern Point strsubfontwidth(Subfont*, char*); extern int loadchar(Font*, Rune, Cacheinfo*, int, int, char**); extern char* subfontname(char*, char*, int); -extern Subfont* _getsubfont(Display*, char*); +extern Subfont* _getsubfont(Display*, Font*, char*); extern Subfont* getdefont(Display*); extern void lockdisplay(Display*); extern void unlockdisplay(Display*);
diff --git a/src/libdraw/buildfont.c b/src/libdraw/buildfont.c index 75b59b1..0f14022 100644 --- a/src/libdraw/buildfont.c +++ b/src/libdraw/buildfont.c
@@ -25,6 +25,7 @@ if(fnt == 0) return 0; memset(fnt, 0, sizeof(Font)); + fnt->scale = 1; fnt->display = d; fnt->name = strdup(name); fnt->ncache = NFCACHE+NFLOOK;
diff --git a/src/libdraw/getsubfont.c b/src/libdraw/getsubfont.c index 0d8be9f..3f3b695 100644 --- a/src/libdraw/getsubfont.c +++ b/src/libdraw/getsubfont.c
@@ -8,8 +8,10 @@ int _fontpipe(char*); +static void scalesubfont(Subfont*, int); + Subfont* -_getsubfont(Display *d, char *name) +_getsubfont(Display *d, Font *ff, char *name) { int fd; Subfont *f; @@ -36,5 +38,61 @@ 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); return f; } + +static void +scalesubfont(Subfont *f, int scale) +{ + Image *i; + Rectangle r, r2; + int y, x, x2, j; + uchar *src, *dst; + int srcn, dstn, n, mask, v, pack; + + r = f->bits->r; + r2 = r; + r2.min.x *= scale; + r2.min.y *= scale; + r2.max.x *= scale; + r2.max.y *= scale; + + srcn = bytesperline(r, f->bits->depth); + src = malloc(srcn); + dstn = bytesperline(r2, f->bits->depth); + dst = malloc(dstn+1); + i = allocimage(f->bits->display, r2, f->bits->chan, 0, DBlack); + for(y=r.min.y; y < r.max.y; y++) { + n = unloadimage(f->bits, Rect(r.min.x, y, r.max.x, y+1), src, srcn); + if(n != srcn) + sysfatal("scalesubfont: bad unload: %d < %d: %r", n, srcn); + memset(dst, 0, dstn+1); + pack = 8 / f->bits->depth; + mask = (1<<f->bits->depth) - 1; + for(x=0; x<Dx(r); x++) { + v = ((src[x/pack] << ((x%pack)*f->bits->depth)) >> (8 - f->bits->depth)) & mask; + for(j=0; j<scale; j++) { + x2 = x*scale+j; + dst[x2/pack] |= v << (8 - f->bits->depth) >> ((x2%pack)*f->bits->depth); + } + } + if(dst[dstn] != 0) + sysfatal("overflow dst"); + for(j=0; j<scale; j++) + loadimage(i, Rect(r2.min.x, y*scale+j, r2.max.x, y*scale+j+1), dst, dstn); + } + freeimage(f->bits); + f->bits = i; + f->height *= scale; + f->ascent *= scale; + + for(j=0; j<f->n; j++) { + f->info[j].x *= scale; + f->info[j].top *= scale; + f->info[j].bottom *= scale; + f->info[j].left *= scale; + f->info[j].width *= scale; + } +}
diff --git a/src/libdraw/mkfont.c b/src/libdraw/mkfont.c index df6b0ec..cb8ab22 100644 --- a/src/libdraw/mkfont.c +++ b/src/libdraw/mkfont.c
@@ -15,6 +15,7 @@ if(font == 0) return 0; memset(font, 0, sizeof(Font)); + font->scale = 1; font->display = subfont->bits->display; font->name = strdup("<synthetic>"); font->ncache = NFCACHE+NFLOOK;
diff --git a/src/libdraw/openfont.c b/src/libdraw/openfont.c index 892f7f6..ae1462d 100644 --- a/src/libdraw/openfont.c +++ b/src/libdraw/openfont.c
@@ -9,10 +9,15 @@ openfont(Display *d, char *name) { Font *fnt; - int fd, i, n; + int fd, i, n, scale; char *buf, *nambuf; nambuf = 0; + scale = 1; + if('1' <= name[0] && name[0] <= '9' && name[1] == '*') { + scale = name[0] - '0'; + name += 2; + } fd = open(name, OREAD); if(fd < 0 && strncmp(name, "/lib/font/bit/", 14) == 0){ @@ -54,6 +59,12 @@ fnt = buildfont(d, buf, name); free(buf); free(nambuf); + if(scale != 1) { + fnt->scale = scale; + fnt->height *= scale; + fnt->ascent *= scale; + fnt->width *= scale; + } return fnt; }
diff --git a/src/libdraw/string.c b/src/libdraw/string.c index 392a7e8..c84112e 100644 --- a/src/libdraw/string.c +++ b/src/libdraw/string.c
@@ -130,7 +130,7 @@ } if(subfontname){ freesubfont(sf); - if((sf=_getsubfont(f->display, subfontname)) == 0){ + if((sf=_getsubfont(f->display, f, 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 522fbc0..e4630ca 100644 --- a/src/libdraw/stringwidth.c +++ b/src/libdraw/stringwidth.c
@@ -48,7 +48,7 @@ } if(subfontname){ freesubfont(sf); - if((sf=_getsubfont(f->display, subfontname)) == 0){ + if((sf=_getsubfont(f->display, f, subfontname)) == 0){ def = f->display ? f->display->defaultfont : nil; if(def && f!=def) f = def;