tlibdraw: add 2*font syntax for scaled fonts - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 77f23268f7073b254e91748d4764768bab6d6f1f
 (DIR) parent 32dc15fa62d94c88f0b62bfe4d64ba60fe1733a6
 (HTM) Author: Russ Cox <rsc@swtch.com>
       Date:   Tue, 17 Feb 2015 00:57:10 -0500
       
       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>
       
       Diffstat:
         M include/draw.h                      |       3 ++-
         M src/libdraw/buildfont.c             |       1 +
         M src/libdraw/getsubfont.c            |      60 ++++++++++++++++++++++++++++++-
         M src/libdraw/mkfont.c                |       1 +
         M src/libdraw/openfont.c              |      13 ++++++++++++-
         M src/libdraw/string.c                |       2 +-
         M src/libdraw/stringwidth.c           |       2 +-
       
       7 files changed, 77 insertions(+), 5 deletions(-)
       ---
 (DIR) diff --git a/include/draw.h b/include/draw.h
       t@@ -314,6 +314,7 @@ struct Font
                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 */
       t@@ -482,7 +483,7 @@ 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*, char*);
       +extern Subfont*        _getsubfont(Display*, Font*, char*);
        extern Subfont*        getdefont(Display*);
        extern void                lockdisplay(Display*);
        extern void        unlockdisplay(Display*);
 (DIR) diff --git a/src/libdraw/buildfont.c b/src/libdraw/buildfont.c
       t@@ -25,6 +25,7 @@ buildfont(Display *d, char *buf, char *name)
                if(fnt == 0)
                        return 0;
                memset(fnt, 0, sizeof(Font));
       +        fnt->scale = 1;
                fnt->display = d;
                fnt->name = strdup(name);
                fnt->ncache = NFCACHE+NFLOOK;
 (DIR) diff --git a/src/libdraw/getsubfont.c b/src/libdraw/getsubfont.c
       t@@ -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;
       t@@ -36,5 +38,61 @@ _getsubfont(Display *d, 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);
                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;
       +        }
       +}
 (DIR) diff --git a/src/libdraw/mkfont.c b/src/libdraw/mkfont.c
       t@@ -15,6 +15,7 @@ mkfont(Subfont *subfont, Rune min)
                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;
 (DIR) diff --git a/src/libdraw/openfont.c b/src/libdraw/openfont.c
       t@@ -9,10 +9,15 @@ Font*
        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){
       t@@ -54,6 +59,12 @@ openfont(Display *d, char *name)
                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;
        }
        
 (DIR) diff --git a/src/libdraw/string.c b/src/libdraw/string.c
       t@@ -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, subfontname)) == 0){
       +                        if((sf=_getsubfont(f->display, f, subfontname)) == 0){
                                        def = f->display ? f->display->defaultfont : nil;
                                        if(def && f!=def)
                                                f = def;
 (DIR) diff --git a/src/libdraw/stringwidth.c b/src/libdraw/stringwidth.c
       t@@ -48,7 +48,7 @@ _stringnwidth(Font *f, char *s, Rune *r, int len)
                                }
                                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;