2003-09-30 17:47:42 +00:00
|
|
|
#include <u.h>
|
|
|
|
|
#include <libc.h>
|
|
|
|
|
#include <draw.h>
|
2018-11-15 23:52:05 -05:00
|
|
|
#include "defont.h"
|
2003-09-30 17:47:42 +00:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Default version: treat as file name
|
|
|
|
|
*/
|
|
|
|
|
|
2009-07-08 21:43:14 -07:00
|
|
|
int _fontpipe(char*);
|
2018-11-15 23:52:05 -05:00
|
|
|
static int defaultpipe(void);
|
2009-07-08 21:43:14 -07:00
|
|
|
|
2015-02-17 00:57:10 -05:00
|
|
|
static void scalesubfont(Subfont*, int);
|
|
|
|
|
|
2003-09-30 17:47:42 +00:00
|
|
|
Subfont*
|
2015-02-17 12:16:20 -05:00
|
|
|
_getsubfont(Display *d, char *name)
|
2003-09-30 17:47:42 +00:00
|
|
|
{
|
|
|
|
|
int fd;
|
|
|
|
|
Subfont *f;
|
2015-02-17 12:16:20 -05:00
|
|
|
int scale;
|
|
|
|
|
char *fname;
|
2018-11-15 23:52:05 -05:00
|
|
|
|
2015-02-17 12:16:20 -05:00
|
|
|
scale = parsefontscale(name, &fname);
|
2018-11-15 23:52:05 -05:00
|
|
|
if(strcmp(fname, "*default*") == 0)
|
|
|
|
|
fd = defaultpipe();
|
|
|
|
|
else
|
|
|
|
|
fd = open(fname, OREAD);
|
2015-02-17 12:16:20 -05:00
|
|
|
if(fd < 0 && strncmp(fname, "/mnt/font/", 10) == 0)
|
|
|
|
|
fd = _fontpipe(fname+10);
|
2003-09-30 17:47:42 +00:00
|
|
|
if(fd < 0){
|
2015-02-17 12:16:20 -05:00
|
|
|
fprint(2, "getsubfont: can't open %s: %r\n", fname);
|
2003-09-30 17:47:42 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* unlock display so i/o happens with display released, unless
|
|
|
|
|
* user is doing his own locking, in which case this could break things.
|
|
|
|
|
* _getsubfont is called only from string.c and stringwidth.c,
|
|
|
|
|
* which are known to be safe to have this done.
|
|
|
|
|
*/
|
2004-04-25 20:26:27 +00:00
|
|
|
if(d && d->locking == 0)
|
2003-09-30 17:47:42 +00:00
|
|
|
unlockdisplay(d);
|
2004-04-25 20:26:27 +00:00
|
|
|
f = readsubfont(d, name, fd, d && d->locking==0);
|
|
|
|
|
if(d && d->locking == 0)
|
2003-09-30 17:47:42 +00:00
|
|
|
lockdisplay(d);
|
|
|
|
|
if(f == 0)
|
|
|
|
|
fprint(2, "getsubfont: can't read %s: %r\n", name);
|
|
|
|
|
close(fd);
|
2015-02-17 12:16:20 -05:00
|
|
|
if(scale > 1)
|
|
|
|
|
scalesubfont(f, scale);
|
2003-09-30 17:47:42 +00:00
|
|
|
return f;
|
|
|
|
|
}
|
2015-02-17 00:57:10 -05:00
|
|
|
|
2018-11-15 23:52:05 -05:00
|
|
|
static int
|
|
|
|
|
defaultpipe(void)
|
|
|
|
|
{
|
2020-01-14 13:18:29 -05:00
|
|
|
int p[2], pid;
|
2018-11-15 23:52:05 -05:00
|
|
|
|
2020-01-14 13:18:29 -05:00
|
|
|
// Used to assume that defontdata (<5k) fit in the
|
|
|
|
|
// pipe buffer, especially since p9pipe is actually
|
|
|
|
|
// a socket pair. But OpenBSD in particular saw hangs,
|
|
|
|
|
// so feed the pipe it the "right" way with a subprocess.
|
2018-11-15 23:52:05 -05:00
|
|
|
if(pipe(p) < 0)
|
|
|
|
|
return -1;
|
2020-01-14 13:18:29 -05:00
|
|
|
if((pid = fork()) < 0) {
|
|
|
|
|
close(p[0]);
|
|
|
|
|
close(p[1]);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(pid == 0) {
|
|
|
|
|
close(p[0]);
|
|
|
|
|
write(p[1], defontdata, sizeof defontdata);
|
|
|
|
|
close(p[1]);
|
|
|
|
|
_exit(0);
|
|
|
|
|
}
|
2018-11-15 23:52:05 -05:00
|
|
|
return p[0];
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 00:57:10 -05:00
|
|
|
static void
|
|
|
|
|
scalesubfont(Subfont *f, int scale)
|
|
|
|
|
{
|
|
|
|
|
Image *i;
|
|
|
|
|
Rectangle r, r2;
|
|
|
|
|
int y, x, x2, j;
|
|
|
|
|
uchar *src, *dst;
|
|
|
|
|
int srcn, dstn, n, mask, v, pack;
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2015-02-17 00:57:10 -05:00
|
|
|
r = f->bits->r;
|
|
|
|
|
r2 = r;
|
|
|
|
|
r2.min.x *= scale;
|
|
|
|
|
r2.min.y *= scale;
|
|
|
|
|
r2.max.x *= scale;
|
|
|
|
|
r2.max.y *= scale;
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2015-02-17 00:57:10 -05:00
|
|
|
srcn = bytesperline(r, f->bits->depth);
|
|
|
|
|
src = malloc(srcn);
|
|
|
|
|
dstn = bytesperline(r2, f->bits->depth);
|
|
|
|
|
dst = malloc(dstn+1);
|
|
|
|
|
i = allocimage(f->bits->display, r2, f->bits->chan, 0, DBlack);
|
|
|
|
|
for(y=r.min.y; y < r.max.y; y++) {
|
|
|
|
|
n = unloadimage(f->bits, Rect(r.min.x, y, r.max.x, y+1), src, srcn);
|
2018-11-15 23:52:05 -05:00
|
|
|
if(n != srcn) {
|
|
|
|
|
abort();
|
|
|
|
|
sysfatal("scalesubfont: bad unload %R %R: %d < %d: %r", f->bits->r, Rect(r.min.x, y, r.max.x, y+1), n, srcn);
|
|
|
|
|
}
|
2015-02-17 00:57:10 -05:00
|
|
|
memset(dst, 0, dstn+1);
|
|
|
|
|
pack = 8 / f->bits->depth;
|
|
|
|
|
mask = (1<<f->bits->depth) - 1;
|
|
|
|
|
for(x=0; x<Dx(r); x++) {
|
|
|
|
|
v = ((src[x/pack] << ((x%pack)*f->bits->depth)) >> (8 - f->bits->depth)) & mask;
|
|
|
|
|
for(j=0; j<scale; j++) {
|
|
|
|
|
x2 = x*scale+j;
|
|
|
|
|
dst[x2/pack] |= v << (8 - f->bits->depth) >> ((x2%pack)*f->bits->depth);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(dst[dstn] != 0)
|
|
|
|
|
sysfatal("overflow dst");
|
|
|
|
|
for(j=0; j<scale; j++)
|
|
|
|
|
loadimage(i, Rect(r2.min.x, y*scale+j, r2.max.x, y*scale+j+1), dst, dstn);
|
|
|
|
|
}
|
|
|
|
|
freeimage(f->bits);
|
|
|
|
|
f->bits = i;
|
|
|
|
|
f->height *= scale;
|
|
|
|
|
f->ascent *= scale;
|
2020-01-10 14:44:21 +00:00
|
|
|
|
2023-08-20 20:57:39 -04:00
|
|
|
for(j=0; j<=f->n; j++) {
|
2015-02-17 00:57:10 -05:00
|
|
|
f->info[j].x *= scale;
|
|
|
|
|
f->info[j].top *= scale;
|
|
|
|
|
f->info[j].bottom *= scale;
|
|
|
|
|
f->info[j].left *= scale;
|
|
|
|
|
f->info[j].width *= scale;
|
|
|
|
|
}
|
|
|
|
|
}
|