diff options
author | Russ Cox <rsc@swtch.com> | 2009-07-08 21:43:14 -0700 |
---|---|---|
committer | Russ Cox <rsc@swtch.com> | 2009-07-08 21:43:14 -0700 |
commit | 9b4a2324d39a8c952c8184249d2b06b9349205a2 (patch) | |
tree | a721c194fb6772ffb668aeb548f9ceaef9f56dce | |
parent | 4a18fa68b01bf8121a8660d3f5214e5927763251 (diff) | |
parent | 4a18fa68b01bf8121a8660d3f5214e5927763251 (diff) | |
download | plan9port-9b4a2324d39a8c952c8184249d2b06b9349205a2.tar.gz plan9port-9b4a2324d39a8c952c8184249d2b06b9349205a2.tar.bz2 plan9port-9b4a2324d39a8c952c8184249d2b06b9349205a2.zip |
merge
-rw-r--r-- | include/9p.h | 1 | ||||
-rw-r--r-- | man/man1/9term.1 | 2 | ||||
-rw-r--r-- | man/man4/fontsrv.4 | 126 | ||||
-rw-r--r-- | src/cmd/fontsrv/a.h | 23 | ||||
-rw-r--r-- | src/cmd/fontsrv/main.c | 594 | ||||
-rw-r--r-- | src/cmd/fontsrv/mkfile | 14 | ||||
-rw-r--r-- | src/cmd/fontsrv/nowsys.c | 21 | ||||
-rw-r--r-- | src/cmd/fontsrv/osx.c | 292 | ||||
-rw-r--r-- | src/cmd/fontsrv/x11.c | 2 | ||||
-rw-r--r-- | src/lib9p/srv.c | 3 | ||||
-rw-r--r-- | src/libdraw/getsubfont.c | 6 | ||||
-rw-r--r-- | src/libdraw/openfont.c | 61 | ||||
-rw-r--r-- | src/libdraw/subfontname.c | 2 |
13 files changed, 1140 insertions, 7 deletions
diff --git a/include/9p.h b/include/9p.h index 77efeb4e..a72d460c 100644 --- a/include/9p.h +++ b/include/9p.h @@ -206,6 +206,7 @@ struct Srv { int leavefdsopen; /* magic for acme win */ int dotu; int foreground; /* run in foreground */ + int fake; /* below is implementation-specific; don't use */ Fidpool* fpool; diff --git a/man/man1/9term.1 b/man/man1/9term.1 index 484f2d3c..a2f21384 100644 --- a/man/man1/9term.1 +++ b/man/man1/9term.1 @@ -158,7 +158,7 @@ for the preceding string (see .PP Text may be moved vertically within the window. A scroll bar on the left of the window shows in its clear portion what fragment of the -total output text is visible on the screen, and in its gray part what +total output text is visible on the screen, and in its grey part what is above or below view; it measures characters, not lines. Mousing inside the scroll bar moves text: diff --git a/man/man4/fontsrv.4 b/man/man4/fontsrv.4 new file mode 100644 index 00000000..3bad44ae --- /dev/null +++ b/man/man4/fontsrv.4 @@ -0,0 +1,126 @@ +.TH FONTSRV 4 +.SH NAME +fontsrv \- file system access to host fonts +.SH SYNOPSIS +.B fontsrv +[ +.B -m +.I mtpt +] +.PP +.B fontsrv +.B -p +.I path +.SH DESCRIPTION +.I Fontsrv +presents the host window system's fonts +in the standard Plan 9 format +(see +.IR font (7)). +It serves a virtual directory tree mounted at +.I mtpt +(if the +.B -m +option is given) +and posted at +.I srvname +(default +.IR font ). +.PP +The +.B -p +option changes +.I fontsrv 's +behavior: rather than serve a file system, +.I fontsrv +prints to standard output the contents of the named +.IR path . +If +.I path +names a directory in the served file system, +.I fontsrv +lists the directory's contents. +.PP +The fonts are arranged in a two-level tree. +The root contains directories named for each system font. +Each font directory contains subdirectories named for +a point size and whether the subfonts are anti-aliased: +.B 10 +(bitmap) +.BR 10a +(anti-aliased greyscale) +.BR 12 , +.BR 12a , +and so on. +The font directory will synthesize additional sizes on +demand: looking up +.B 19a +will synthesize the 19-point anti-aliased size +if possible. +Each size directory contains a +.B font +file and subfont files +named +.BR x0000.bit , +.BR x0100.bit , +and so on +representing 256-character Unicode ranges. +.PP +.I Openfont +(see +.IR graphics (3)) +recognizes font paths beginning with +.B /mnt/font +and implements them by invoking +.IR fontsrv ; +it need not be running already. +.SH EXAMPLES +List the fonts on the system: +.IP +.EX +% fontsrv & +% 9p ls font +.EE +.LP +or: +.IP +.EX +% fontsrv -p . +.EE +.LP +Run +.IR acme (1) +using the operating system's Monaco as the fixed-width font: +.IP +.EX +% acme -F /mnt/font/Monaco/13a/font +.EE +.LP +Run +.IR sam (1) +using the same font: +.IP +.EX +font=/mnt/font/Monaco/13a/font sam +.EE +.SH SOURCE +.B \*9/src/cmd/fontsrv +.SH SEE ALSO +.IR font (7) +.SH BUGS +.PP +Due to OS X restrictions, +.I fontsrv +does not fork itself into the background +when serving a user-level file system. +.PP +.I Fontsrv +has no support for X11 fonts; +on X11 systems, it will serve an empty top-level directory. +.PP +On OS X, the anti-aliased bitmaps are not perfect. +For example, the lower case r in the subfont +.B Times-Roman/14a/x0000.bit +appears truncated on the right and +too light overall. + diff --git a/src/cmd/fontsrv/a.h b/src/cmd/fontsrv/a.h new file mode 100644 index 00000000..0781fbab --- /dev/null +++ b/src/cmd/fontsrv/a.h @@ -0,0 +1,23 @@ +typedef struct XFont XFont; +XFont *xfont; +int nxfont; + +struct XFont +{ + char *name; + int loaded; + uchar range[256]; // range[i] == whether to have subfont i<<8 to (i+1)<<8. + int nrange; + int unit; + double height; + double originy; +}; + +void loadfonts(void); +void load(XFont*); +Memsubfont* mksubfont(char*, int, int, int, int); + +extern XFont *xfont; +extern int nxfont; +void *emalloc9p(ulong); +extern Memsubfont *defont; diff --git a/src/cmd/fontsrv/main.c b/src/cmd/fontsrv/main.c new file mode 100644 index 00000000..c8a179df --- /dev/null +++ b/src/cmd/fontsrv/main.c @@ -0,0 +1,594 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <memdraw.h> +#include <thread.h> +#include <fcall.h> +#include <9p.h> +/* + * we included thread.h in order to include 9p.h, + * but we don't use threads, so exits is ok. + */ +#undef exits + +#include "a.h" + +Memsubfont *defont; + +void +usage(void) +{ + fprint(2, "usage: fontsrv [-m mtpt]\n"); + fprint(2, "or fontsrv -p path\n"); + exits("usage"); +} + +static +void +packinfo(Fontchar *fc, uchar *p, int n) +{ + int j; + + for(j=0; j<=n; j++){ + p[0] = fc->x; + p[1] = fc->x>>8; + p[2] = fc->top; + p[3] = fc->bottom; + p[4] = fc->left; + p[5] = fc->width; + fc++; + p += 6; + } +} + +enum +{ + Qroot = 0, + Qfontdir, + Qsizedir, + Qfontfile, + Qsubfontfile, +}; + +#define QTYPE(p) ((p) & 0xF) +#define QFONT(p) (((p) >> 4) & 0xFFFF) +#define QSIZE(p) (((p) >> 20) & 0xFF) +#define QANTIALIAS(p) (((p) >> 28) & 0x1) +#define QRANGE(p) (((p) >> 29) & 0xFF) +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 +qpath(int type, int font, int size, int antialias, int range) +{ + return type | (font << 4) | (size << 20) | (antialias << 28) | ((vlong)range << 29); +} + +static void +dostat(vlong path, Qid *qid, Dir *dir) +{ + char *name; + Qid q; + ulong mode; + vlong length; + XFont *f; + char buf[100]; + + q.type = 0; + q.vers = 0; + q.path = path; + mode = 0444; + length = 0; + name = "???"; + + switch(QTYPE(path)) { + default: + sysfatal("dostat %#llux", path); + + case Qroot: + q.type = QTDIR; + name = "/"; + break; + + case Qfontdir: + q.type = QTDIR; + f = &xfont[QFONT(path)]; + name = f->name; + break; + + case Qsizedir: + q.type = QTDIR; + snprint(buf, sizeof buf, "%lld%s", QSIZE(path), QANTIALIAS(path) ? "a" : ""); + name = buf; + break; + + case Qfontfile: + f = &xfont[QFONT(path)]; + load(f); + length = 11+1+11+1+f->nrange*(6+1+6+1+9+1); + name = "font"; + break; + + case Qsubfontfile: + snprint(buf, sizeof buf, "x%02llx00.bit", QRANGE(path)); + name = buf; + break; + } + + if(qid) + *qid = q; + if(dir) { + memset(dir, 0, sizeof *dir); + dir->name = estrdup9p(name); + dir->muid = estrdup9p(""); + dir->uid = estrdup9p("font"); + dir->gid = estrdup9p("font"); + dir->qid = q; + if(q.type == QTDIR) + mode |= DMDIR | 0111; + dir->mode = mode; + dir->length = length; + } +} + +static char* +xwalk1(Fid *fid, char *name, Qid *qid) +{ + int i, dotdot; + vlong path; + char *p; + int a, n; + XFont *f; + + path = fid->qid.path; + dotdot = strcmp(name, "..") == 0; + switch(QTYPE(path)) { + default: + NotFound: + return "file not found"; + + case Qroot: + if(dotdot) + break; + for(i=0; i<nxfont; i++) { + if(strcmp(xfont[i].name, name) == 0) { + path = qpath(Qfontdir, i, 0, 0, 0); + goto Found; + } + } + goto NotFound; + + case Qfontdir: + if(dotdot) { + path = Qroot; + break; + } + n = strtol(name, &p, 10); + if(n == 0) + goto NotFound; + a = 0; + if(*p == 'a') { + a = 1; + p++; + } + if(*p != 0) + goto NotFound; + path += Qsizedir - Qfontdir + qpath(0, 0, n, a, 0); + break; + + case Qsizedir: + if(dotdot) { + path = qpath(Qfontdir, QFONT(path), 0, 0, 0); + break; + } + if(strcmp(name, "font") == 0) { + path += Qfontfile - Qsizedir; + break; + } + f = &xfont[QFONT(path)]; + load(f); + p = name; + if(*p != 'x') + goto NotFound; + p++; + n = strtoul(p, &p, 16); + if(p != name+5 || (n&0xFF) != 0 || strcmp(p, ".bit") != 0 || !f->range[(n>>8) & 0xFF]) + goto NotFound; + path += Qsubfontfile - Qsizedir + qpath(0, 0, 0, 0, (n>>8) & 0xFF); + break; + } +Found: + dostat(path, qid, nil); + fid->qid = *qid; + return nil; +} + +static int +rootgen(int i, Dir *d, void *v) +{ + if(i >= nxfont) + return -1; + dostat(qpath(Qfontdir, i, 0, 0, 0), nil, d); + return 0; +} + +static int +fontgen(int i, Dir *d, void *v) +{ + vlong path; + Fid *f; + + f = v; + path = f->qid.path; + if(i >= 2*nelem(sizes)) + return -1; + dostat(qpath(Qsizedir, QFONT(path), sizes[i/2], i&1, 0), nil, d); + return 0; +} + +static int +sizegen(int i, Dir *d, void *v) +{ + vlong path; + Fid *fid; + XFont *f; + int j; + + fid = v; + path = fid->qid.path; + if(i == 0) { + path += Qfontfile - Qsizedir; + goto Done; + } + 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--; + } + return -1; + +Done: + dostat(path, nil, d); + return 0; +} + +static void +xattach(Req *r) +{ + dostat(0, &r->ofcall.qid, nil); + r->fid->qid = r->ofcall.qid; + respond(r, nil); +} + +static void +xopen(Req *r) +{ + if(r->ifcall.mode != OREAD) { + respond(r, "permission denied"); + return; + } + r->ofcall.qid = r->fid->qid; + respond(r, nil); +} + +void +responderrstr(Req *r) +{ + char err[ERRMAX]; + + rerrstr(err, sizeof err); + respond(r, err); +} + +static void +xread(Req *r) +{ + int i, size, height, ascent; + vlong path; + Fmt fmt; + XFont *f; + char *data; + Memsubfont *sf; + Memimage *m; + + path = r->fid->qid.path; + switch(QTYPE(path)) { + case Qroot: + dirread9p(r, rootgen, nil); + break; + case Qfontdir: + dirread9p(r, fontgen, r->fid); + break; + case Qsizedir: + dirread9p(r, sizegen, r->fid); + break; + case Qfontfile: + fmtstrinit(&fmt); + f = &xfont[QFONT(path)]; + load(f); + if(f->unit == 0) + break; + height = f->height * (int)QSIZE(path)/f->unit + 0.99999999; + ascent = height - (int)(-f->originy * (int)QSIZE(path)/f->unit + 0.99999999); + 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<<8, (i<<8) + 0xFF, i<<8); + } + data = fmtstrflush(&fmt); + readstr(r, data); + free(data); + break; + case Qsubfontfile: + f = &xfont[QFONT(path)]; + load(f); + if(r->fid->aux == nil) { + r->fid->aux = mksubfont(f->name, QRANGE(path)<<8, (QRANGE(path)<<8)+0xFF, QSIZE(path), QANTIALIAS(path)); + if(r->fid->aux == nil) { + responderrstr(r); + return; + } + } + sf = r->fid->aux; + m = sf->bits; + if(r->ifcall.offset < 5*12) { + char *chan; + if(QANTIALIAS(path)) + chan = "k8"; + else + chan = "k1"; + data = smprint("%11s %11d %11d %11d %11d ", chan, m->r.min.x, m->r.min.y, m->r.max.x, m->r.max.y); + readstr(r, data); + free(data); + break; + } + r->ifcall.offset -= 5*12; + size = bytesperline(m->r, chantodepth(m->chan)) * Dy(m->r); + if(r->ifcall.offset < size) { + readbuf(r, byteaddr(m, m->r.min), size); + break; + } + r->ifcall.offset -= size; + data = emalloc9p(3*12+6*(sf->n+1)); + sprint(data, "%11d %11d %11d ", sf->n, sf->height, sf->ascent); + packinfo(sf->info, (uchar*)data+3*12, sf->n); + readbuf(r, data, 3*12+6*(sf->n+1)); + free(data); + break; + } + respond(r, nil); +} + +static void +xdestroyfid(Fid *fid) +{ + Memsubfont *sf; + + sf = fid->aux; + if(sf == nil) + return; + + freememimage(sf->bits); + free(sf->info); + free(sf); + fid->aux = nil; +} + +static void +xstat(Req *r) +{ + dostat(r->fid->qid.path, nil, &r->d); + respond(r, nil); +} + +Srv xsrv; + +int +proccreate(void (*f)(void*), void *a, unsigned i) +{ + abort(); +} + +int pflag; + +static long dirpackage(uchar*, long, Dir**); + +void +dump(char *path) +{ + char *elem, *p, *path0, *err; + uchar buf[4096]; + Fid fid; + Qid qid; + Dir *d; + Req r; + int off, i, n; + + // root + memset(&fid, 0, sizeof fid); + dostat(0, &fid.qid, nil); + qid = fid.qid; + + path0 = path; + while(path != nil) { + p = strchr(path, '/'); + if(p != nil) + *p = '\0'; + elem = path; + if(strcmp(elem, "") != 0 && strcmp(elem, ".") != 0) { + err = xwalk1(&fid, elem, &qid); + if(err != nil) { + fprint(2, "%s: %s\n", path0, err); + exits(err); + } + } + if(p) + *p++ = '/'; + path = p; + } + + memset(&r, 0, sizeof r); + xsrv.fake = 1; + + // read and display + off = 0; + for(;;) { + r.srv = &xsrv; + r.fid = &fid; + r.ifcall.type = Tread; + r.ifcall.count = sizeof buf; + r.ifcall.offset = off; + r.ofcall.data = (char*)buf; + r.ofcall.count = 0; + xread(&r); + if(r.ofcall.type != Rread) { + fprint(2, "reading %s: %s\n", path0, r.ofcall.ename); + exits(r.ofcall.ename); + } + n = r.ofcall.count; + if(n == 0) + break; + if(off == 0 && pflag > 1) { + print("\001"); + } + off += n; + if(qid.type & QTDIR) { + n = dirpackage(buf, n, &d); + for(i=0; i<n; i++) + print("%s%s\n", d[i].name, (d[i].mode&DMDIR) ? "/" : ""); + free(d); + } else + write(1, buf, n); + } +} + +int +fontcmp(const void *va, const void *vb) +{ + XFont *a, *b; + + a = (XFont*)va; + b = (XFont*)vb; + return strcmp(a->name, b->name); +} + +void +main(int argc, char **argv) +{ + char *mtpt; + + mtpt = unsharp("#9/font/mnt"); + + ARGBEGIN{ + case 'D': + chatty9p++; + break; + case 'F': + chattyfuse++; + break; + case 'm': + mtpt = EARGF(usage()); + break; + case 'p': + pflag++; + break; + default: + usage(); + }ARGEND + + xsrv.attach = xattach; + xsrv.open = xopen; + xsrv.read = xread; + xsrv.stat = xstat; + xsrv.walk1 = xwalk1; + xsrv.destroyfid = xdestroyfid; + + fmtinstall('R', Rfmt); + fmtinstall('P', Pfmt); + memimageinit(); + defont = getmemdefont(); + loadfonts(); + qsort(xfont, nxfont, sizeof xfont[0], fontcmp); + + if(pflag) { + if(argc != 1 || chatty9p || chattyfuse) + usage(); + dump(argv[0]); + exits(0); + } + + if(pflag || argc != 0) + usage(); + + /* + * Check twice -- if there is an exited instance + * mounted there, the first access will fail but unmount it. + */ + if(mtpt && access(mtpt, AEXIST) < 0 && access(mtpt, AEXIST) < 0) + sysfatal("mountpoint %s does not exist", mtpt); + + xsrv.foreground = 1; + threadpostmountsrv(&xsrv, "font", mtpt, 0); +} + +/* + /sys/src/libc/9sys/dirread.c +*/ +static +long +dirpackage(uchar *buf, long ts, Dir **d) +{ + char *s; + long ss, i, n, nn, m; + + *d = nil; + if(ts <= 0) + return 0; + + /* + * first find number of all stats, check they look like stats, & size all associated strings + */ + ss = 0; + n = 0; + for(i = 0; i < ts; i += m){ + m = BIT16SZ + GBIT16(&buf[i]); + if(statcheck(&buf[i], m) < 0) + break; + ss += m; + n++; + } + + if(i != ts) + return -1; + + *d = malloc(n * sizeof(Dir) + ss); + if(*d == nil) + return -1; + + /* + * then convert all buffers + */ + s = (char*)*d + n * sizeof(Dir); + nn = 0; + for(i = 0; i < ts; i += m){ + m = BIT16SZ + GBIT16((uchar*)&buf[i]); + if(nn >= n || convM2D(&buf[i], m, *d + nn, s) != m){ + free(*d); + *d = nil; + return -1; + } + nn++; + s += m; + } + + return nn; +} + diff --git a/src/cmd/fontsrv/mkfile b/src/cmd/fontsrv/mkfile new file mode 100644 index 00000000..27b6b3ce --- /dev/null +++ b/src/cmd/fontsrv/mkfile @@ -0,0 +1,14 @@ +<|sh ../devdraw/mkwsysrules.sh +<$PLAN9/src/mkhdr + +TARG=fontsrv + +HFILES=a.h + +OFILES=\ + main.$O\ + $WSYSTYPE.$O\ + +<$PLAN9/src/mkone + + diff --git a/src/cmd/fontsrv/nowsys.c b/src/cmd/fontsrv/nowsys.c new file mode 100644 index 00000000..eb3b57a9 --- /dev/null +++ b/src/cmd/fontsrv/nowsys.c @@ -0,0 +1,21 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <memdraw.h> +#include "a.h" + +void +loadfonts(void) +{ +} + +void +load(XFont *f) +{ +} + +Memsubfont* +mksubfont(char *name, int lo, int hi, int size, int antialias) +{ + return nil; +} diff --git a/src/cmd/fontsrv/osx.c b/src/cmd/fontsrv/osx.c new file mode 100644 index 00000000..94190d19 --- /dev/null +++ b/src/cmd/fontsrv/osx.c @@ -0,0 +1,292 @@ +#include <u.h> + +#define Point OSXPoint +#define Rect OSXRect +#define Cursor OSXCursor +#include <Carbon/Carbon.h> +#undef Rect +#undef Point +#undef Cursor +#undef offsetof +#undef nil + +#include <libc.h> +#include <draw.h> +#include <memdraw.h> +#include "a.h" + + +extern void CGFontGetGlyphsForUnichars(CGFontRef, const UniChar[], const CGGlyph[], size_t); + +char* +mac2c(CFStringRef s) +{ + char *p; + int n; + + n = CFStringGetLength(s)*8; + p = malloc(n); + CFStringGetCString(s, p, n, kCFStringEncodingUTF8); + return p; +} + +CFStringRef +c2mac(char *p) +{ + return CFStringCreateWithBytes(nil, (uchar*)p, strlen(p), kCFStringEncodingUTF8, false); +} + +Rectangle +mac2r(CGRect r, int size, int unit) +{ + Rectangle rr; + + rr.min.x = r.origin.x*size/unit; + rr.min.y = r.origin.y*size/unit; + rr.max.x = (r.origin.x+r.size.width)*size/unit + 0.99999999; + rr.max.y = (r.origin.x+r.size.width)*size/unit + 0.99999999; + return rr; +} + +void +loadfonts(void) +{ + int i, n; + CTFontCollectionRef allc; + CFArrayRef array; + CFStringRef s; + CTFontDescriptorRef f; + + allc = CTFontCollectionCreateFromAvailableFonts(0); + array = CTFontCollectionCreateMatchingFontDescriptors(allc); + n = CFArrayGetCount(array); + xfont = emalloc9p(n*sizeof xfont[0]); + for(i=0; i<n; i++) { + f = (void*)CFArrayGetValueAtIndex(array, i); + if(f == nil) + continue; + s = CTFontDescriptorCopyAttribute(f, kCTFontNameAttribute); + xfont[nxfont].name = mac2c(s); + CFRelease(s); + nxfont++; + } +} + +CGRect +subfontbbox(CGFontRef font, int lo, int hi) +{ + int i, first; + CGRect bbox; + + bbox.origin.x = 0; + bbox.origin.y = 0; + bbox.size.height = 0; + bbox.size.width = 0; + + first = 1; + for(i=lo; i<=hi; i++) { + UniChar u; + CGGlyph g; + CGRect r; + + u = i; + CGFontGetGlyphsForUnichars(font, &u, &g, 1); + if(g == 0 || !CGFontGetGlyphBBoxes(font, &g, 1, &r)) + continue; + + r.size.width += r.origin.x; + r.size.height += r.origin.y; + if(first) { + bbox = r; + first = 0; + continue; + } + if(bbox.origin.x > r.origin.x) + bbox.origin.x = r.origin.x; + if(bbox.origin.y > r.origin.y) + bbox.origin.y = r.origin.y; + if(bbox.size.width < r.size.width) + bbox.size.width = r.size.width; + if(bbox.size.height < r.size.height) + bbox.size.height = r.size.height; + } + + bbox.size.width -= bbox.origin.x; + bbox.size.height -= bbox.origin.y; + return bbox; +} + +void +load(XFont *f) +{ + int i, j; + CGFontRef font; + CFStringRef s; + UniChar u[256]; + CGGlyph g[256]; + CGRect bbox; + + if(f->loaded) + return; + f->loaded = 1; + s = c2mac(f->name); + font = CGFontCreateWithFontName(s); + CFRelease(s); + if(font == nil) + return; + + // assume bbox gives latin1 is height/ascent for all + bbox = subfontbbox(font, 0x00, 0xff); + f->unit = CGFontGetUnitsPerEm(font); + f->height = bbox.size.height; + f->originy = bbox.origin.y; + + // figure out where the letters are + for(i=0; i<0xffff; i+=0x100) { + for(j=0; j<0x100; j++) { + u[j] = i+j; + g[j] = 0; + } + CGFontGetGlyphsForUnichars(font, u, g, 256); + for(j=0; j<0x100; j++) { + if(g[j] != 0) { + f->range[i>>8] = 1; + f->nrange++; + break; + } + } + } + CFRelease(font); +} + +Memsubfont* +mksubfont(char *name, int lo, int hi, int size, int antialias) +{ + CFStringRef s; + CGColorSpaceRef color; + CGContextRef ctxt; + CGFontRef font; + CGRect bbox; + Memimage *m, *mc, *m1; + int x, y, y0; + int i, unit; + Fontchar *fc, *fc0; + Memsubfont *sf; + + s = c2mac(name); + font = CGFontCreateWithFontName(s); + CFRelease(s); + if(font == nil) + return nil; + bbox = subfontbbox(font, lo, hi); + unit = CGFontGetUnitsPerEm(font); + x = (int)(bbox.size.width * size / unit + 0.99999999); + y = bbox.size.height * size/unit + 0.99999999; + y0 = (int)(-bbox.origin.y * size/unit + 0.99999999); + m = allocmemimage(Rect(0, 0, x*(hi+1-lo), y), GREY8); + if(m == nil) + return nil; + mc = allocmemimage(Rect(0, 0, x, y), GREY8); + if(mc == nil) + return nil; + memfillcolor(m, DBlack); + memfillcolor(mc, DBlack); + fc = malloc((hi+2 - lo) * sizeof fc[0]); + sf = malloc(sizeof *sf); + if(fc == nil || sf == nil) { + freememimage(m); + freememimage(mc); + free(fc); + free(sf); + return nil; + } + fc0 = fc; + + color = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); + ctxt = CGBitmapContextCreate(byteaddr(mc, mc->r.min), Dx(mc->r), Dy(mc->r), 8, + mc->width*sizeof(u32int), color, kCGImageAlphaNone); + CGColorSpaceRelease(color); + if(ctxt == nil) { + freememimage(m); + freememimage(mc); + free(fc); + free(sf); + return nil; + } + + CGContextSetFont(ctxt, font); + CGContextSetFontSize(ctxt, size); + CGContextSetAllowsAntialiasing(ctxt, antialias); + CGContextSetRGBFillColor(ctxt, 1, 1, 1, 1); + CGContextSetTextPosition(ctxt, 0, 0); // XXX + + x = 0; + for(i=lo; i<=hi; i++, fc++) { + UniChar u[2]; + CGGlyph g[2]; + CGRect r[2]; + CGPoint p1; + int n; + + fc->x = x; + fc->top = 0; + fc->bottom = Dy(m->r); + + n = 0; + u[n++] = i; + if(0) // debugging + u[n++] = '|'; + g[0] = 0; + CGFontGetGlyphsForUnichars(font, u, g, n); + if(g[0] == 0 || !CGFontGetGlyphBBoxes(font, g, n, r)) { + None: + fc->width = 0; + if(i == 0) { + Point p; + Fontchar *i; + p = Pt(x, y0); + // memimagestring(m, p, memwhite, ZP, defont, peterface); + i = defont->info + 0; + memdraw(m, Rect(p.x+i->left, p.y+i->top, p.x+i->left+(i[1].x-i[0].x), p.y+i->bottom), + memwhite, ZP, defont->bits, Pt(i->x, i->top), S); + p.x += i->width; + fc->left = i->left; + fc->width = i->width; + x = p.x; + } + continue; + } + memfillcolor(mc, DBlack); + CGContextSetTextPosition(ctxt, 0, y0); + CGContextShowGlyphs(ctxt, g, n); + p1 = CGContextGetTextPosition(ctxt); + if(p1.x <= 0) + goto None; + memimagedraw(m, Rect(x, 0, x + p1.x, y), mc, ZP, memopaque, ZP, S); + fc->width = p1.x; + fc->left = 0; + x += p1.x; + } + fc->x = x; + + // round up to 32-bit boundary + // so that in-memory data is same + // layout as in-file data. + if(antialias) + x += -x & 3; + else + x += -x & 31; + m1 = allocmemimage(Rect(0, 0, x, y), antialias ? GREY8 : GREY1); + memimagedraw(m1, m1->r, m, m->r.min, memopaque, ZP, S); + freememimage(m); + + sf->name = nil; + sf->n = hi+1 - lo; + sf->height = Dy(m1->r); + sf->ascent = Dy(m1->r) - y0; + sf->info = fc0; + sf->bits = m1; + + return sf; +} + diff --git a/src/cmd/fontsrv/x11.c b/src/cmd/fontsrv/x11.c new file mode 100644 index 00000000..f1fb3cd9 --- /dev/null +++ b/src/cmd/fontsrv/x11.c @@ -0,0 +1,2 @@ +/* maybe someday */ +#include "nowsys.c" diff --git a/src/lib9p/srv.c b/src/lib9p/srv.c index 0e7c3113..ece35940 100644 --- a/src/lib9p/srv.c +++ b/src/lib9p/srv.c @@ -794,6 +794,9 @@ respond(Req *r, char *error) if(r->error) setfcallerror(&r->ofcall, r->error); + if(srv->fake) + return; + if(chatty9p) fprint(2, "-%d-> %F\n", srv->outfd, &r->ofcall); diff --git a/src/libdraw/getsubfont.c b/src/libdraw/getsubfont.c index 2cbec812..0d8be9ff 100644 --- a/src/libdraw/getsubfont.c +++ b/src/libdraw/getsubfont.c @@ -6,6 +6,8 @@ * Default version: treat as file name */ +int _fontpipe(char*); + Subfont* _getsubfont(Display *d, char *name) { @@ -13,7 +15,9 @@ _getsubfont(Display *d, char *name) Subfont *f; fd = open(name, OREAD); - + if(fd < 0 && strncmp(name, "/mnt/font/", 10) == 0) + fd = _fontpipe(name+10); + if(fd < 0){ fprint(2, "getsubfont: can't open %s: %r\n", name); return 0; diff --git a/src/libdraw/openfont.c b/src/libdraw/openfont.c index 05370eac..892f7f61 100644 --- a/src/libdraw/openfont.c +++ b/src/libdraw/openfont.c @@ -3,6 +3,7 @@ #include <draw.h> extern vlong _drawflength(int); +int _fontpipe(char*); Font* openfont(Display *d, char *name) @@ -27,26 +28,78 @@ openfont(Display *d, char *name) } name = nambuf; } + if(fd >= 0) + n = _drawflength(fd); + if(fd < 0 && strncmp(name, "/mnt/font/", 10) == 0) { + fd = _fontpipe(name+10); + n = 8192; + } if(fd < 0) return 0; - n = _drawflength(fd); buf = malloc(n+1); if(buf == 0){ close(fd); free(nambuf); return 0; } - buf[n] = 0; - i = read(fd, buf, n); + i = readn(fd, buf, n); close(fd); - if(i != n){ + if(i <= 0){ free(buf); free(nambuf); return 0; } + buf[i] = 0; fnt = buildfont(d, buf, name); free(buf); free(nambuf); return fnt; } + +int +_fontpipe(char *name) +{ + int p[2]; + char c; + char buf[1024], *argv[10]; + int nbuf, pid; + + if(pipe(p) < 0) + return -1; + pid = rfork(RFNOWAIT|RFFDG|RFPROC); + if(pid < 0) { + close(p[0]); + close(p[1]); + return -1; + } + if(pid == 0) { + close(p[0]); + dup(p[1], 1); + dup(p[1], 2); + if(p[1] > 2) + close(p[1]); + argv[0] = "fontsrv"; + argv[1] = "-pp"; + argv[2] = name; + argv[3] = nil; + execvp("fontsrv", argv); + print("exec fontsrv: %r\n"); + _exit(0); + } + close(p[1]); + + // success marked with leading \001. + // otherwise an error happened. + for(nbuf=0; nbuf<sizeof buf-1; nbuf++) { + if(read(p[0], &c, 1) < 1 || c == '\n') { + buf[nbuf] = '\0'; + werrstr(buf); + close(p[0]); + return -1; + } + if(c == '\001') + break; + } + return p[0]; +} diff --git a/src/libdraw/subfontname.c b/src/libdraw/subfontname.c index 1374ef31..874528be 100644 --- a/src/libdraw/subfontname.c +++ b/src/libdraw/subfontname.c @@ -43,7 +43,7 @@ subfontname(char *cfname, char *fname, int maxdepth) } /* try default */ - if(access(t, AREAD) == 0) + if(strncmp(t, "/mnt/font/", 10) == 0 || access(t, AREAD) == 0) return t; return nil; |