URI: 
       tfree subfonts correctly - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit b2f9ee0de55f3c59c83f479d12cfe8c894935bd7
   DIR parent 3b634dc7e4ab32a6854c8ec93107b2750bf906e8
  HTML Author: rsc <devnull@localhost>
       Date:   Wed, 13 Jul 2005 03:57:24 +0000
       
       free subfonts correctly
       
       Diffstat:
         M src/libdraw/string.c                |      11 +++++++++--
         M src/libdraw/stringwidth.c           |      13 +++++++++++--
         M src/libdraw/subfont.c               |      14 ++++++++++++--
       
       3 files changed, 32 insertions(+), 6 deletions(-)
       ---
   DIR diff --git a/src/libdraw/string.c b/src/libdraw/string.c
       t@@ -65,6 +65,7 @@ _string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, i
                char **sptr;
                Rune **rptr;
                Font *def;
       +        Subfont *sf;
        
                if(s == nil){
                        s = "";
       t@@ -76,6 +77,7 @@ _string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, i
                        rptr = nil;
                }else
                        rptr = &r;
       +        sf = nil;
                while((*s || *r) && len){
                        max = Max;
                        if(len < max)
       t@@ -124,13 +126,18 @@ _string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, i
                                len -= n;
                        }
                        if(subfontname){
       -                        if(_getsubfont(f->display, subfontname) == 0){
       -                                def = f->display->defaultfont;
       +                        freesubfont(sf);
       +                        if((sf=_getsubfont(f->display, subfontname)) == 0){
       +                                def = f->display ? f->display->defaultfont : nil;
                                        if(def && f!=def)
                                                f = def;
                                        else
                                                break;
                                }
       +                        /* 
       +                         * must not free sf until cachechars has found it in the cache
       +                         * and picked up its own reference.
       +                         */
                        }
                }
                return pt;
   DIR diff --git a/src/libdraw/stringwidth.c b/src/libdraw/stringwidth.c
       t@@ -13,6 +13,7 @@ _stringnwidth(Font *f, char *s, Rune *r, int len)
                Rune rune, **rptr;
                char *subfontname, **sptr;
                Font *def;
       +        Subfont *sf;
        
                if(s == nil){
                        s = "";
       t@@ -30,6 +31,7 @@ _stringnwidth(Font *f, char *s, Rune *r, int len)
                        if(len < max)
                                max = len;
                        n = 0;
       +                sf = nil;
                        while((l = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname)) <= 0){
                                if(++n > 10){
                                        if(*r)
       t@@ -40,19 +42,26 @@ _stringnwidth(Font *f, char *s, Rune *r, int len)
                                                name = f->name;
                                        else
                                                name = "unnamed font";
       +                                freesubfont(sf);
                                        fprint(2, "stringwidth: bad character set for rune 0x%.4ux in %s\n", rune, name);
                                        return twid;
                                }
                                if(subfontname){
       -                                if(_getsubfont(f->display, subfontname) == 0){
       -                                        def = f->display->defaultfont;
       +                                freesubfont(sf);
       +                                if((sf=_getsubfont(f->display, subfontname)) == 0){
       +                                        def = f->display ? f->display->defaultfont : nil;
                                                if(def && f!=def)
                                                        f = def;
                                                else
                                                        break;
                                        }
       +                                /* 
       +                                 * must not free sf until cachechars has found it in the cache
       +                                 * and picked up its own reference.
       +                                 */
                                }
                        }
       +                freesubfont(sf);
                        agefont(f);
                        twid += wid;
                        len -= l;
   DIR diff --git a/src/libdraw/subfont.c b/src/libdraw/subfont.c
       t@@ -5,13 +5,14 @@
        Subfont*
        allocsubfont(char *name, int n, int height, int ascent, Fontchar *info, Image *i)
        {
       -        Subfont *f;
       +        Subfont *f, *cf;
        
                assert(height != 0 /* allocsubfont */);
        
                f = malloc(sizeof(Subfont));
                if(f == 0)
                        return 0;
       +fprint(2, "allocsubfont %p\n", f);
                f->n = n;
                f->height = height;
                f->ascent = ascent;
       t@@ -19,9 +20,18 @@ allocsubfont(char *name, int n, int height, int ascent, Fontchar *info, Image *i
                f->bits = i;
                f->ref = 1;
                if(name){
       +                /*
       +                 * if already caching this subfont, leave older 
       +                 * (and hopefully more widely used) copy in cache.
       +                 * this case should not happen -- we got called 
       +                 * because cachechars needed this subfont and it
       +                 * wasn't in the cache.
       +                 */
                        f->name = strdup(name);
       -                if(lookupsubfont(i->display, name) == 0)
       +                if((cf=lookupsubfont(i->display, name)) == 0)
                                installsubfont(name, f);
       +                else
       +                        freesubfont(cf);        /* drop ref we just picked up */
                }else
                        f->name = 0;
                return f;