diff options
author | rsc <devnull@localhost> | 2005-01-04 21:23:50 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2005-01-04 21:23:50 +0000 |
commit | 24c02865d8fcc97d1fb5cb9281810d8074aa5eb1 (patch) | |
tree | 3bb16794ded14341ee58d9f1f173ce92fb4d2be7 /src/cmd/page/gfx.c | |
parent | d1e9002f81f14fbfef1ebc4261edccd9eb97b72c (diff) | |
download | plan9port-24c02865d8fcc97d1fb5cb9281810d8074aa5eb1.tar.gz plan9port-24c02865d8fcc97d1fb5cb9281810d8074aa5eb1.tar.bz2 plan9port-24c02865d8fcc97d1fb5cb9281810d8074aa5eb1.zip |
placeholder; does not yet build
Diffstat (limited to 'src/cmd/page/gfx.c')
-rw-r--r-- | src/cmd/page/gfx.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/src/cmd/page/gfx.c b/src/cmd/page/gfx.c new file mode 100644 index 00000000..72254de8 --- /dev/null +++ b/src/cmd/page/gfx.c @@ -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]; +} + |