tfontsrv: handle non-BMP runes on X11 - 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 5f0fa185d0a978b45de5bf206193769596c056b5
 (DIR) parent a6ad39aaaa36b8aadc5c35bfc803afbde32918c0
 (HTM) Author: Russ Cox <rsc@swtch.com>
       Date:   Tue, 26 May 2020 11:36:59 -0400
       
       fontsrv: handle non-BMP runes on X11
       
       Have to adjust algorithms to deal with
       much larger number of subfont files as well.
       
       Diffstat:
         M src/cmd/fontsrv/a.h                 |       9 ++++++---
         M src/cmd/fontsrv/mac.c               |       6 ++++--
         M src/cmd/fontsrv/main.c              |      53 ++++++++++++++-----------------
         M src/cmd/fontsrv/x11.c               |      19 +++++++++++--------
       
       4 files changed, 44 insertions(+), 43 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/fontsrv/a.h b/src/cmd/fontsrv/a.h
       t@@ -4,19 +4,22 @@ int nxfont;
        
        enum {
                SubfontSize = 32,
       -        SubfontMask = (1<<16)/SubfontSize - 1,
       +        MaxSubfont = (Runemax+1)/SubfontSize,
        };
        
        struct XFont
        {
                char *name;
                int loaded;
       -        uchar range[(1<<16)/SubfontSize];        // range[i] == whether to have subfont i*SubfontSize to (i+1)*SubfontSize - 1.
       -        int nrange;
       +        uchar range[MaxSubfont]; // range[i] = fontfile starting at i*SubfontSize exists
       +        ushort file[MaxSubfont];        // file[i] == fontfile i's lo rune / SubfontSize
       +        int nfile;
                int unit;
                double height;
                double originy;
                void (*loadheight)(XFont*, int, int*, int*);
       +        char *fonttext;
       +        int nfonttext;
        
                // fontconfig workarround, as FC_FULLNAME does not work for matching fonts.
                char *fontfile;
 (DIR) diff --git a/src/cmd/fontsrv/mac.c b/src/cmd/fontsrv/mac.c
       t@@ -200,9 +200,12 @@ load(XFont *f)
                f->loadheight = fontheight;
        
                // enable all Unicode ranges
       +        if(nelem(f->file) > 0xffff)
       +                sysfatal("too many subfiles"); // f->file holds ushorts
                for(i=0; i<nelem(f->range); i++) {
                        f->range[i] = 1;
       -                f->nrange++;
       +                f->file[i] = i;
       +                f->nfile++;
                }
        }
        
       t@@ -233,7 +236,6 @@ mksubfont(XFont *f, char *name, int lo, int hi, int size, int antialias)
                if(font == nil)
                        return nil;
        
       -
                bbox = CTFontGetBoundingBox(font);
                x = (int)(bbox.size.width*2 + 0.99999999);
        
 (DIR) diff --git a/src/cmd/fontsrv/main.c b/src/cmd/fontsrv/main.c
       t@@ -52,7 +52,7 @@ enum
        #define QFONT(p) (((p) >> 4) & 0xFFFF)
        #define QSIZE(p) (((p) >> 20) & 0xFF)
        #define QANTIALIAS(p) (((p) >> 28) & 0x1)
       -#define QRANGE(p) (((p) >> 29) & SubfontMask)
       +#define QRANGE(p) (((p) >> 29) & 0xFFFFFF)
        static int sizes[] = { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, 28 };
        
        static vlong
       t@@ -102,7 +102,7 @@ dostat(vlong path, Qid *qid, Dir *dir)
                case Qfontfile:
                        f = &xfont[QFONT(path)];
                        load(f);
       -                length = 11+1+11+1+f->nrange*(6+1+6+1+9+1);
       +                length = 11+1+11+1+f->nfile*(6+1+6+1+9+1);
                        name = "font";
                        break;
        
       t@@ -189,9 +189,9 @@ xwalk1(Fid *fid, char *name, Qid *qid)
                                goto NotFound;
                        p++;
                        n = strtoul(p, &p, 16);
       -                if(p != name+5 || n%SubfontSize != 0 || strcmp(p, ".bit") != 0 || !f->range[(n/SubfontSize) & SubfontMask])
       +                if(p < name+5 || p > name+5 && name[1] == '0' || n%SubfontSize != 0 || n/SubfontSize >= MaxSubfont || strcmp(p, ".bit") != 0 || !f->range[n/SubfontSize])
                                goto NotFound;
       -                path += Qsubfontfile - Qsizedir + qpath(0, 0, 0, 0, (n/SubfontSize) & SubfontMask);
       +                path += Qsubfontfile - Qsizedir + qpath(0, 0, 0, 0, n/SubfontSize);
                        break;
                }
        Found:
       t@@ -229,7 +229,6 @@ sizegen(int i, Dir *d, void *v)
                vlong path;
                Fid *fid;
                XFont *f;
       -        int j;
        
                fid = v;
                path = fid->qid.path;
       t@@ -240,15 +239,10 @@ sizegen(int i, Dir *d, void *v)
                i--;
                f = &xfont[QFONT(path)];
                load(f);
       -        for(j=0; j<nelem(f->range); j++) {
       -                if(f->range[j] == 0)
       -                        continue;
       -                if(i == 0) {
       -                        path += Qsubfontfile - Qsizedir;
       -                        path += qpath(0, 0, 0, 0, j);
       -                        goto Done;
       -                }
       -                i--;
       +        if(i < f->nfile) {
       +                path += Qsubfontfile - Qsizedir;
       +                path += qpath(0, 0, 0, 0, f->file[i]);
       +                goto Done;
                }
                return -1;
        
       t@@ -315,23 +309,22 @@ xread(Req *r)
                                readstr(r, "font missing\n");
                                break;
                        }
       -                height = 0;
       -                ascent = 0;
       -                if(f->unit > 0) {
       -                        height = f->height * (int)QSIZE(path)/f->unit + 0.99999999;
       -                        ascent = height - (int)(-f->originy * (int)QSIZE(path)/f->unit + 0.99999999);
       -                }
       -                if(f->loadheight != nil)
       -                        f->loadheight(f, QSIZE(path), &height, &ascent);
       -                fmtprint(&fmt, "%11d %11d\n", height, ascent);
       -                for(i=0; i<nelem(f->range); i++) {
       -                        if(f->range[i] == 0)
       -                                continue;
       -                        fmtprint(&fmt, "0x%04x 0x%04x x%04x.bit\n", i*SubfontSize, ((i+1)*SubfontSize) - 1, i*SubfontSize);
       +                if(f->fonttext == nil) {
       +                        height = 0;
       +                        ascent = 0;
       +                        if(f->unit > 0) {
       +                                height = f->height * (int)QSIZE(path)/f->unit + 0.99999999;
       +                                ascent = height - (int)(-f->originy * (int)QSIZE(path)/f->unit + 0.99999999);
       +                        }
       +                        if(f->loadheight != nil)
       +                                f->loadheight(f, QSIZE(path), &height, &ascent);
       +                        fmtprint(&fmt, "%11d %11d\n", height, ascent);
       +                        for(i=0; i<f->nfile; i++)
       +                                fmtprint(&fmt, "0x%04x 0x%04x x%04x.bit\n", f->file[i]*SubfontSize, ((f->file[i]+1)*SubfontSize) - 1, f->file[i]*SubfontSize);
       +                        f->fonttext = fmtstrflush(&fmt);
       +                        f->nfonttext = strlen(f->fonttext);
                        }
       -                data = fmtstrflush(&fmt);
       -                readstr(r, data);
       -                free(data);
       +                readbuf(r, f->fonttext, f->nfonttext);
                        break;
                case Qsubfontfile:
                        f = &xfont[QFONT(path)];
 (DIR) diff --git a/src/cmd/fontsrv/x11.c b/src/cmd/fontsrv/x11.c
       t@@ -85,20 +85,23 @@ load(XFont *f)
        
                        int idx = charcode/SubfontSize;
        
       -                if(charcode > 0xffff)
       +                if(charcode > Runemax)
                                break;
        
       -                if(!f->range[idx]) {
       +                if(!f->range[idx])
                                f->range[idx] = 1;
       -                        f->nrange++;
       -                }
                }
       +        FT_Done_Face(face);
       +
                // libdraw expects U+0000 to be present
       -        if(!f->range[0]) {
       +        if(!f->range[0])
                        f->range[0] = 1;
       -                f->nrange++;
       -        }
       -        FT_Done_Face(face);
       +
       +        // fix up file list
       +        for(i=0; i<nelem(f->range); i++)
       +                if(f->range[i])
       +                        f->file[f->nfile++] = i;
       +
                f->loaded = 1;
        }