This commit is contained in:
Russ Cox 2009-07-08 21:43:14 -07:00
commit 9b4a2324d3
13 changed files with 1140 additions and 7 deletions

View file

@ -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;

View file

@ -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:

126
man/man4/fontsrv.4 Normal file
View file

@ -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.

23
src/cmd/fontsrv/a.h Normal file
View file

@ -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;

594
src/cmd/fontsrv/main.c Normal file
View file

@ -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;
}

14
src/cmd/fontsrv/mkfile Normal file
View file

@ -0,0 +1,14 @@
<|sh ../devdraw/mkwsysrules.sh
<$PLAN9/src/mkhdr
TARG=fontsrv
HFILES=a.h
OFILES=\
main.$O\
$WSYSTYPE.$O\
<$PLAN9/src/mkone

21
src/cmd/fontsrv/nowsys.c Normal file
View file

@ -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;
}

292
src/cmd/fontsrv/osx.c Normal file
View file

@ -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;
}

2
src/cmd/fontsrv/x11.c Normal file
View file

@ -0,0 +1,2 @@
/* maybe someday */
#include "nowsys.c"

View file

@ -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);

View file

@ -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;

View file

@ -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];
}

View file

@ -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;