merge
This commit is contained in:
commit
9b4a2324d3
13 changed files with 1140 additions and 7 deletions
|
|
@ -206,6 +206,7 @@ struct Srv {
|
||||||
int leavefdsopen; /* magic for acme win */
|
int leavefdsopen; /* magic for acme win */
|
||||||
int dotu;
|
int dotu;
|
||||||
int foreground; /* run in foreground */
|
int foreground; /* run in foreground */
|
||||||
|
int fake;
|
||||||
|
|
||||||
/* below is implementation-specific; don't use */
|
/* below is implementation-specific; don't use */
|
||||||
Fidpool* fpool;
|
Fidpool* fpool;
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ for the preceding string (see
|
||||||
.PP
|
.PP
|
||||||
Text may be moved vertically within the window.
|
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
|
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;
|
is above or below view;
|
||||||
it measures characters, not lines.
|
it measures characters, not lines.
|
||||||
Mousing inside the scroll bar moves text:
|
Mousing inside the scroll bar moves text:
|
||||||
|
|
|
||||||
126
man/man4/fontsrv.4
Normal file
126
man/man4/fontsrv.4
Normal 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
23
src/cmd/fontsrv/a.h
Normal 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
594
src/cmd/fontsrv/main.c
Normal 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
14
src/cmd/fontsrv/mkfile
Normal 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
21
src/cmd/fontsrv/nowsys.c
Normal 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
292
src/cmd/fontsrv/osx.c
Normal 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
2
src/cmd/fontsrv/x11.c
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
/* maybe someday */
|
||||||
|
#include "nowsys.c"
|
||||||
|
|
@ -794,6 +794,9 @@ respond(Req *r, char *error)
|
||||||
if(r->error)
|
if(r->error)
|
||||||
setfcallerror(&r->ofcall, r->error);
|
setfcallerror(&r->ofcall, r->error);
|
||||||
|
|
||||||
|
if(srv->fake)
|
||||||
|
return;
|
||||||
|
|
||||||
if(chatty9p)
|
if(chatty9p)
|
||||||
fprint(2, "-%d-> %F\n", srv->outfd, &r->ofcall);
|
fprint(2, "-%d-> %F\n", srv->outfd, &r->ofcall);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
* Default version: treat as file name
|
* Default version: treat as file name
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int _fontpipe(char*);
|
||||||
|
|
||||||
Subfont*
|
Subfont*
|
||||||
_getsubfont(Display *d, char *name)
|
_getsubfont(Display *d, char *name)
|
||||||
{
|
{
|
||||||
|
|
@ -13,6 +15,8 @@ _getsubfont(Display *d, char *name)
|
||||||
Subfont *f;
|
Subfont *f;
|
||||||
|
|
||||||
fd = open(name, OREAD);
|
fd = open(name, OREAD);
|
||||||
|
if(fd < 0 && strncmp(name, "/mnt/font/", 10) == 0)
|
||||||
|
fd = _fontpipe(name+10);
|
||||||
|
|
||||||
if(fd < 0){
|
if(fd < 0){
|
||||||
fprint(2, "getsubfont: can't open %s: %r\n", name);
|
fprint(2, "getsubfont: can't open %s: %r\n", name);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include <draw.h>
|
#include <draw.h>
|
||||||
|
|
||||||
extern vlong _drawflength(int);
|
extern vlong _drawflength(int);
|
||||||
|
int _fontpipe(char*);
|
||||||
|
|
||||||
Font*
|
Font*
|
||||||
openfont(Display *d, char *name)
|
openfont(Display *d, char *name)
|
||||||
|
|
@ -27,26 +28,78 @@ openfont(Display *d, char *name)
|
||||||
}
|
}
|
||||||
name = nambuf;
|
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)
|
if(fd < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
n = _drawflength(fd);
|
|
||||||
buf = malloc(n+1);
|
buf = malloc(n+1);
|
||||||
if(buf == 0){
|
if(buf == 0){
|
||||||
close(fd);
|
close(fd);
|
||||||
free(nambuf);
|
free(nambuf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
buf[n] = 0;
|
i = readn(fd, buf, n);
|
||||||
i = read(fd, buf, n);
|
|
||||||
close(fd);
|
close(fd);
|
||||||
if(i != n){
|
if(i <= 0){
|
||||||
free(buf);
|
free(buf);
|
||||||
free(nambuf);
|
free(nambuf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
buf[i] = 0;
|
||||||
fnt = buildfont(d, buf, name);
|
fnt = buildfont(d, buf, name);
|
||||||
free(buf);
|
free(buf);
|
||||||
free(nambuf);
|
free(nambuf);
|
||||||
return fnt;
|
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];
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ subfontname(char *cfname, char *fname, int maxdepth)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try default */
|
/* try default */
|
||||||
if(access(t, AREAD) == 0)
|
if(strncmp(t, "/mnt/font/", 10) == 0 || access(t, AREAD) == 0)
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue