tfontsrv: handle non-BMP runes on X11 - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
commit 5f0fa185d0a978b45de5bf206193769596c056b5
parent a6ad39aaaa36b8aadc5c35bfc803afbde32918c0
Author: Russ Cox 
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(-)
---
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;
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; irange); 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);
 
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; jrange); 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; irange); 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; infile; 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)];
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; irange); i++)
+                if(f->range[i])
+                        f->file[f->nfile++] = i;
+
         f->loaded = 1;
 }