placeholder; does not yet build
This commit is contained in:
parent
d1e9002f81
commit
24c02865d8
13 changed files with 3661 additions and 0 deletions
331
src/cmd/page/gfx.c
Normal file
331
src/cmd/page/gfx.c
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* graphics file reading for page
|
||||
*/
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <event.h>
|
||||
#include <bio.h>
|
||||
#include "page.h"
|
||||
|
||||
typedef struct Convert Convert;
|
||||
typedef struct GfxInfo GfxInfo;
|
||||
typedef struct Graphic Graphic;
|
||||
|
||||
struct Convert {
|
||||
char *name;
|
||||
char *cmd;
|
||||
char *truecmd; /* cmd for true color */
|
||||
};
|
||||
|
||||
struct GfxInfo {
|
||||
Graphic *g;
|
||||
};
|
||||
|
||||
struct Graphic {
|
||||
int type;
|
||||
char *name;
|
||||
uchar *buf; /* if stdin */
|
||||
int nbuf;
|
||||
};
|
||||
|
||||
enum {
|
||||
Ipic,
|
||||
Itiff,
|
||||
Ijpeg,
|
||||
Igif,
|
||||
Iinferno,
|
||||
Ifax,
|
||||
Icvt2pic,
|
||||
Iplan9bm,
|
||||
Iccittg4,
|
||||
Ippm,
|
||||
Ipng,
|
||||
Iyuv,
|
||||
Ibmp,
|
||||
};
|
||||
|
||||
/*
|
||||
* N.B. These commands need to read stdin if %a is replaced
|
||||
* with an empty string.
|
||||
*/
|
||||
Convert cvt[] = {
|
||||
[Ipic] { "plan9", "fb/3to1 rgbv %a |fb/pcp -tplan9" },
|
||||
[Itiff] { "tiff", "fb/tiff2pic %a | fb/3to1 rgbv | fb/pcp -tplan9" },
|
||||
[Iplan9bm] { "plan9bm", nil },
|
||||
[Ijpeg] { "jpeg", "jpg -9 %a", "jpg -t9 %a" },
|
||||
[Igif] { "gif", "gif -9 %a", "gif -t9 %a" },
|
||||
[Iinferno] { "inferno", nil },
|
||||
[Ifax] { "fax", "aux/g3p9bit -g %a" },
|
||||
[Icvt2pic] { "unknown", "fb/cvt2pic %a |fb/3to1 rgbv" },
|
||||
[Ippm] { "ppm", "ppm -9 %a", "ppm -t9 %a" },
|
||||
/* ``temporary'' hack for hobby */
|
||||
[Iccittg4] { "ccitt-g4", "cat %a|rx nslocum /usr/lib/ocr/bin/bcp -M|fb/pcp -tcompressed -l0" },
|
||||
[Ipng] { "png", "png -9 %a", "png -t9 %a" },
|
||||
[Iyuv] { "yuv", "yuv -9 %a", "yuv -t9 %a" },
|
||||
[Ibmp] { "bmp", "bmp -9 %a", "bmp -t9 %a" },
|
||||
};
|
||||
|
||||
static Image* convert(Graphic*);
|
||||
static Image* gfxdrawpage(Document *d, int page);
|
||||
static char* gfxpagename(Document*, int);
|
||||
static int spawnrc(char*, uchar*, int);
|
||||
static int addpage(Document*, char*);
|
||||
static int rmpage(Document*, int);
|
||||
static int genaddpage(Document*, char*, uchar*, int);
|
||||
|
||||
static char*
|
||||
gfxpagename(Document *doc, int page)
|
||||
{
|
||||
GfxInfo *gfx = doc->extra;
|
||||
return gfx->g[page].name;
|
||||
}
|
||||
|
||||
static Image*
|
||||
gfxdrawpage(Document *doc, int page)
|
||||
{
|
||||
GfxInfo *gfx = doc->extra;
|
||||
return convert(gfx->g+page);
|
||||
}
|
||||
|
||||
Document*
|
||||
initgfx(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
|
||||
{
|
||||
GfxInfo *gfx;
|
||||
Document *doc;
|
||||
int i;
|
||||
|
||||
USED(b);
|
||||
doc = emalloc(sizeof(*doc));
|
||||
gfx = emalloc(sizeof(*gfx));
|
||||
gfx->g = nil;
|
||||
|
||||
doc->npage = 0;
|
||||
doc->drawpage = gfxdrawpage;
|
||||
doc->pagename = gfxpagename;
|
||||
doc->addpage = addpage;
|
||||
doc->rmpage = rmpage;
|
||||
doc->extra = gfx;
|
||||
doc->fwdonly = 0;
|
||||
|
||||
fprint(2, "reading through graphics...\n");
|
||||
if(argc==0 && buf)
|
||||
genaddpage(doc, nil, buf, nbuf);
|
||||
else{
|
||||
for(i=0; i<argc; i++)
|
||||
if(addpage(doc, argv[i]) < 0)
|
||||
fprint(2, "warning: not including %s: %r\n", argv[i]);
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
static int
|
||||
genaddpage(Document *doc, char *name, uchar *buf, int nbuf)
|
||||
{
|
||||
Graphic *g;
|
||||
GfxInfo *gfx;
|
||||
Biobuf *b;
|
||||
uchar xbuf[32];
|
||||
int i, l;
|
||||
|
||||
l = 0;
|
||||
gfx = doc->extra;
|
||||
|
||||
assert((name == nil) ^ (buf == nil));
|
||||
assert(name != nil || doc->npage == 0);
|
||||
|
||||
for(i=0; i<doc->npage; i++)
|
||||
if(strcmp(gfx->g[i].name, name) == 0)
|
||||
return i;
|
||||
|
||||
if(name){
|
||||
l = strlen(name);
|
||||
if((b = Bopen(name, OREAD)) == nil) {
|
||||
werrstr("Bopen: %r");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(Bread(b, xbuf, sizeof xbuf) != sizeof xbuf) {
|
||||
werrstr("short read: %r");
|
||||
return -1;
|
||||
}
|
||||
Bterm(b);
|
||||
buf = xbuf;
|
||||
nbuf = sizeof xbuf;
|
||||
}
|
||||
|
||||
|
||||
gfx->g = erealloc(gfx->g, (doc->npage+1)*(sizeof(*gfx->g)));
|
||||
g = &gfx->g[doc->npage];
|
||||
|
||||
memset(g, 0, sizeof *g);
|
||||
if(memcmp(buf, "GIF", 3) == 0)
|
||||
g->type = Igif;
|
||||
else if(memcmp(buf, "\111\111\052\000", 4) == 0)
|
||||
g->type = Itiff;
|
||||
else if(memcmp(buf, "\115\115\000\052", 4) == 0)
|
||||
g->type = Itiff;
|
||||
else if(memcmp(buf, "\377\330\377", 3) == 0)
|
||||
g->type = Ijpeg;
|
||||
else if(memcmp(buf, "\211PNG\r\n\032\n", 3) == 0)
|
||||
g->type = Ipng;
|
||||
else if(memcmp(buf, "compressed\n", 11) == 0)
|
||||
g->type = Iinferno;
|
||||
else if(memcmp(buf, "\0PC Research, Inc", 17) == 0)
|
||||
g->type = Ifax;
|
||||
else if(memcmp(buf, "TYPE=ccitt-g31", 14) == 0)
|
||||
g->type = Ifax;
|
||||
else if(memcmp(buf, "II*", 3) == 0)
|
||||
g->type = Ifax;
|
||||
else if(memcmp(buf, "TYPE=ccitt-g4", 13) == 0)
|
||||
g->type = Iccittg4;
|
||||
else if(memcmp(buf, "TYPE=", 5) == 0)
|
||||
g->type = Ipic;
|
||||
else if(buf[0] == 'P' && '0' <= buf[1] && buf[1] <= '9')
|
||||
g->type = Ippm;
|
||||
else if(memcmp(buf, "BM", 2) == 0)
|
||||
g->type = Ibmp;
|
||||
else if(memcmp(buf, " ", 10) == 0 &&
|
||||
'0' <= buf[10] && buf[10] <= '9' &&
|
||||
buf[11] == ' ')
|
||||
g->type = Iplan9bm;
|
||||
else if(strtochan((char*)buf) != 0)
|
||||
g->type = Iplan9bm;
|
||||
else if (l > 4 && strcmp(name + l -4, ".yuv") == 0)
|
||||
g->type = Iyuv;
|
||||
else
|
||||
g->type = Icvt2pic;
|
||||
|
||||
if(name)
|
||||
g->name = estrdup(name);
|
||||
else{
|
||||
g->name = estrdup("stdin"); /* so it can be freed */
|
||||
g->buf = buf;
|
||||
g->nbuf = nbuf;
|
||||
}
|
||||
|
||||
if(chatty) fprint(2, "classified \"%s\" as \"%s\"\n", g->name, cvt[g->type].name);
|
||||
return doc->npage++;
|
||||
}
|
||||
|
||||
static int
|
||||
addpage(Document *doc, char *name)
|
||||
{
|
||||
return genaddpage(doc, name, nil, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
rmpage(Document *doc, int n)
|
||||
{
|
||||
int i;
|
||||
GfxInfo *gfx;
|
||||
|
||||
if(n < 0 || n >= doc->npage)
|
||||
return -1;
|
||||
|
||||
gfx = doc->extra;
|
||||
doc->npage--;
|
||||
free(gfx->g[n].name);
|
||||
|
||||
for(i=n; i<doc->npage; i++)
|
||||
gfx->g[i] = gfx->g[i+1];
|
||||
|
||||
if(n < doc->npage)
|
||||
return n;
|
||||
if(n == 0)
|
||||
return 0;
|
||||
return n-1;
|
||||
}
|
||||
|
||||
|
||||
static Image*
|
||||
convert(Graphic *g)
|
||||
{
|
||||
int fd;
|
||||
Convert c;
|
||||
char *cmd;
|
||||
char *name, buf[1000];
|
||||
Image *im;
|
||||
int rcspawned = 0;
|
||||
Waitmsg *w;
|
||||
|
||||
c = cvt[g->type];
|
||||
if(c.cmd == nil) {
|
||||
if(chatty) fprint(2, "no conversion for bitmap \"%s\"...\n", g->name);
|
||||
if(g->buf == nil){ /* not stdin */
|
||||
fd = open(g->name, OREAD);
|
||||
if(fd < 0) {
|
||||
fprint(2, "cannot open file: %r\n");
|
||||
wexits("open");
|
||||
}
|
||||
}else
|
||||
fd = stdinpipe(g->buf, g->nbuf);
|
||||
} else {
|
||||
cmd = c.cmd;
|
||||
if(truecolor && c.truecmd)
|
||||
cmd = c.truecmd;
|
||||
|
||||
if(g->buf != nil) /* is stdin */
|
||||
name = "";
|
||||
else
|
||||
name = g->name;
|
||||
if(strlen(cmd)+strlen(name) > sizeof buf) {
|
||||
fprint(2, "command too long\n");
|
||||
wexits("convert");
|
||||
}
|
||||
snprint(buf, sizeof buf, cmd, name);
|
||||
if(chatty) fprint(2, "using \"%s\" to convert \"%s\"...\n", buf, g->name);
|
||||
fd = spawnrc(buf, g->buf, g->nbuf);
|
||||
rcspawned++;
|
||||
if(fd < 0) {
|
||||
fprint(2, "cannot spawn converter: %r\n");
|
||||
wexits("convert");
|
||||
}
|
||||
}
|
||||
|
||||
im = readimage(display, fd, 0);
|
||||
if(im == nil) {
|
||||
fprint(2, "warning: couldn't read image: %r\n");
|
||||
}
|
||||
close(fd);
|
||||
|
||||
/* for some reason rx doesn't work well with wait */
|
||||
/* for some reason 3to1 exits on success with a non-null status of |3to1 */
|
||||
if(rcspawned && g->type != Iccittg4) {
|
||||
if((w=wait())!=nil && w->msg[0] && !strstr(w->msg, "3to1"))
|
||||
fprint(2, "slave wait error: %s\n", w->msg);
|
||||
free(w);
|
||||
}
|
||||
return im;
|
||||
}
|
||||
|
||||
static int
|
||||
spawnrc(char *cmd, uchar *stdinbuf, int nstdinbuf)
|
||||
{
|
||||
int pfd[2];
|
||||
int pid;
|
||||
|
||||
if(chatty) fprint(2, "spawning(%s)...", cmd);
|
||||
|
||||
if(pipe(pfd) < 0)
|
||||
return -1;
|
||||
if((pid = fork()) < 0)
|
||||
return -1;
|
||||
|
||||
if(pid == 0) {
|
||||
close(pfd[1]);
|
||||
if(stdinbuf)
|
||||
dup(stdinpipe(stdinbuf, nstdinbuf), 0);
|
||||
else
|
||||
dup(open("/dev/null", OREAD), 0);
|
||||
dup(pfd[0], 1);
|
||||
//dup(pfd[0], 2);
|
||||
execl("/bin/rc", "rc", "-c", cmd, nil);
|
||||
wexits("exec");
|
||||
}
|
||||
close(pfd[0]);
|
||||
return pfd[1];
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue