Blame


1 24c02865 2005-01-04 devnull /*
2 24c02865 2005-01-04 devnull * graphics file reading for page
3 24c02865 2005-01-04 devnull */
4 24c02865 2005-01-04 devnull
5 24c02865 2005-01-04 devnull #include <u.h>
6 24c02865 2005-01-04 devnull #include <libc.h>
7 24c02865 2005-01-04 devnull #include <draw.h>
8 17157e4a 2006-03-20 devnull #include <cursor.h>
9 24c02865 2005-01-04 devnull #include <event.h>
10 24c02865 2005-01-04 devnull #include <bio.h>
11 24c02865 2005-01-04 devnull #include "page.h"
12 24c02865 2005-01-04 devnull
13 24c02865 2005-01-04 devnull typedef struct Convert Convert;
14 24c02865 2005-01-04 devnull typedef struct GfxInfo GfxInfo;
15 24c02865 2005-01-04 devnull typedef struct Graphic Graphic;
16 24c02865 2005-01-04 devnull
17 24c02865 2005-01-04 devnull struct Convert {
18 24c02865 2005-01-04 devnull char *name;
19 24c02865 2005-01-04 devnull char *cmd;
20 24c02865 2005-01-04 devnull char *truecmd; /* cmd for true color */
21 24c02865 2005-01-04 devnull };
22 24c02865 2005-01-04 devnull
23 24c02865 2005-01-04 devnull struct GfxInfo {
24 24c02865 2005-01-04 devnull Graphic *g;
25 24c02865 2005-01-04 devnull };
26 24c02865 2005-01-04 devnull
27 24c02865 2005-01-04 devnull struct Graphic {
28 24c02865 2005-01-04 devnull int type;
29 24c02865 2005-01-04 devnull char *name;
30 24c02865 2005-01-04 devnull uchar *buf; /* if stdin */
31 24c02865 2005-01-04 devnull int nbuf;
32 24c02865 2005-01-04 devnull };
33 24c02865 2005-01-04 devnull
34 24c02865 2005-01-04 devnull enum {
35 24c02865 2005-01-04 devnull Ipic,
36 24c02865 2005-01-04 devnull Itiff,
37 24c02865 2005-01-04 devnull Ijpeg,
38 24c02865 2005-01-04 devnull Igif,
39 24c02865 2005-01-04 devnull Iinferno,
40 24c02865 2005-01-04 devnull Ifax,
41 24c02865 2005-01-04 devnull Icvt2pic,
42 24c02865 2005-01-04 devnull Iplan9bm,
43 24c02865 2005-01-04 devnull Iccittg4,
44 24c02865 2005-01-04 devnull Ippm,
45 24c02865 2005-01-04 devnull Ipng,
46 24c02865 2005-01-04 devnull Iyuv,
47 cbeb0b26 2006-04-01 devnull Ibmp
48 24c02865 2005-01-04 devnull };
49 24c02865 2005-01-04 devnull
50 24c02865 2005-01-04 devnull /*
51 24c02865 2005-01-04 devnull * N.B. These commands need to read stdin if %a is replaced
52 24c02865 2005-01-04 devnull * with an empty string.
53 24c02865 2005-01-04 devnull */
54 24c02865 2005-01-04 devnull Convert cvt[] = {
55 24c02865 2005-01-04 devnull [Ipic] { "plan9", "fb/3to1 rgbv %a |fb/pcp -tplan9" },
56 24c02865 2005-01-04 devnull [Itiff] { "tiff", "fb/tiff2pic %a | fb/3to1 rgbv | fb/pcp -tplan9" },
57 24c02865 2005-01-04 devnull [Iplan9bm] { "plan9bm", nil },
58 24c02865 2005-01-04 devnull [Ijpeg] { "jpeg", "jpg -9 %a", "jpg -t9 %a" },
59 24c02865 2005-01-04 devnull [Igif] { "gif", "gif -9 %a", "gif -t9 %a" },
60 24c02865 2005-01-04 devnull [Iinferno] { "inferno", nil },
61 24c02865 2005-01-04 devnull [Ifax] { "fax", "aux/g3p9bit -g %a" },
62 24c02865 2005-01-04 devnull [Icvt2pic] { "unknown", "fb/cvt2pic %a |fb/3to1 rgbv" },
63 24c02865 2005-01-04 devnull [Ippm] { "ppm", "ppm -9 %a", "ppm -t9 %a" },
64 24c02865 2005-01-04 devnull /* ``temporary'' hack for hobby */
65 24c02865 2005-01-04 devnull [Iccittg4] { "ccitt-g4", "cat %a|rx nslocum /usr/lib/ocr/bin/bcp -M|fb/pcp -tcompressed -l0" },
66 24c02865 2005-01-04 devnull [Ipng] { "png", "png -9 %a", "png -t9 %a" },
67 24c02865 2005-01-04 devnull [Iyuv] { "yuv", "yuv -9 %a", "yuv -t9 %a" },
68 cbeb0b26 2006-04-01 devnull [Ibmp] { "bmp", "bmp -9 %a", "bmp -t9 %a" }
69 24c02865 2005-01-04 devnull };
70 24c02865 2005-01-04 devnull
71 24c02865 2005-01-04 devnull static Image* convert(Graphic*);
72 24c02865 2005-01-04 devnull static Image* gfxdrawpage(Document *d, int page);
73 24c02865 2005-01-04 devnull static char* gfxpagename(Document*, int);
74 24c02865 2005-01-04 devnull static int spawnrc(char*, uchar*, int);
75 17157e4a 2006-03-20 devnull static void waitrc(void);
76 17157e4a 2006-03-20 devnull static int spawnpost(int);
77 24c02865 2005-01-04 devnull static int addpage(Document*, char*);
78 24c02865 2005-01-04 devnull static int rmpage(Document*, int);
79 24c02865 2005-01-04 devnull static int genaddpage(Document*, char*, uchar*, int);
80 24c02865 2005-01-04 devnull
81 24c02865 2005-01-04 devnull static char*
82 24c02865 2005-01-04 devnull gfxpagename(Document *doc, int page)
83 24c02865 2005-01-04 devnull {
84 24c02865 2005-01-04 devnull GfxInfo *gfx = doc->extra;
85 24c02865 2005-01-04 devnull return gfx->g[page].name;
86 24c02865 2005-01-04 devnull }
87 24c02865 2005-01-04 devnull
88 24c02865 2005-01-04 devnull static Image*
89 24c02865 2005-01-04 devnull gfxdrawpage(Document *doc, int page)
90 24c02865 2005-01-04 devnull {
91 24c02865 2005-01-04 devnull GfxInfo *gfx = doc->extra;
92 24c02865 2005-01-04 devnull return convert(gfx->g+page);
93 24c02865 2005-01-04 devnull }
94 24c02865 2005-01-04 devnull
95 24c02865 2005-01-04 devnull Document*
96 24c02865 2005-01-04 devnull initgfx(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
97 24c02865 2005-01-04 devnull {
98 24c02865 2005-01-04 devnull GfxInfo *gfx;
99 24c02865 2005-01-04 devnull Document *doc;
100 24c02865 2005-01-04 devnull int i;
101 24c02865 2005-01-04 devnull
102 24c02865 2005-01-04 devnull USED(b);
103 17157e4a 2006-03-20 devnull
104 24c02865 2005-01-04 devnull doc = emalloc(sizeof(*doc));
105 24c02865 2005-01-04 devnull gfx = emalloc(sizeof(*gfx));
106 24c02865 2005-01-04 devnull gfx->g = nil;
107 24c02865 2005-01-04 devnull
108 24c02865 2005-01-04 devnull doc->npage = 0;
109 24c02865 2005-01-04 devnull doc->drawpage = gfxdrawpage;
110 24c02865 2005-01-04 devnull doc->pagename = gfxpagename;
111 24c02865 2005-01-04 devnull doc->addpage = addpage;
112 24c02865 2005-01-04 devnull doc->rmpage = rmpage;
113 24c02865 2005-01-04 devnull doc->extra = gfx;
114 24c02865 2005-01-04 devnull doc->fwdonly = 0;
115 24c02865 2005-01-04 devnull
116 24c02865 2005-01-04 devnull fprint(2, "reading through graphics...\n");
117 24c02865 2005-01-04 devnull if(argc==0 && buf)
118 24c02865 2005-01-04 devnull genaddpage(doc, nil, buf, nbuf);
119 24c02865 2005-01-04 devnull else{
120 24c02865 2005-01-04 devnull for(i=0; i<argc; i++)
121 24c02865 2005-01-04 devnull if(addpage(doc, argv[i]) < 0)
122 24c02865 2005-01-04 devnull fprint(2, "warning: not including %s: %r\n", argv[i]);
123 24c02865 2005-01-04 devnull }
124 24c02865 2005-01-04 devnull
125 24c02865 2005-01-04 devnull return doc;
126 24c02865 2005-01-04 devnull }
127 24c02865 2005-01-04 devnull
128 24c02865 2005-01-04 devnull static int
129 24c02865 2005-01-04 devnull genaddpage(Document *doc, char *name, uchar *buf, int nbuf)
130 24c02865 2005-01-04 devnull {
131 24c02865 2005-01-04 devnull Graphic *g;
132 24c02865 2005-01-04 devnull GfxInfo *gfx;
133 24c02865 2005-01-04 devnull Biobuf *b;
134 24c02865 2005-01-04 devnull uchar xbuf[32];
135 24c02865 2005-01-04 devnull int i, l;
136 24c02865 2005-01-04 devnull
137 24c02865 2005-01-04 devnull l = 0;
138 24c02865 2005-01-04 devnull gfx = doc->extra;
139 24c02865 2005-01-04 devnull
140 24c02865 2005-01-04 devnull assert((name == nil) ^ (buf == nil));
141 24c02865 2005-01-04 devnull assert(name != nil || doc->npage == 0);
142 24c02865 2005-01-04 devnull
143 24c02865 2005-01-04 devnull for(i=0; i<doc->npage; i++)
144 24c02865 2005-01-04 devnull if(strcmp(gfx->g[i].name, name) == 0)
145 24c02865 2005-01-04 devnull return i;
146 24c02865 2005-01-04 devnull
147 24c02865 2005-01-04 devnull if(name){
148 24c02865 2005-01-04 devnull l = strlen(name);
149 24c02865 2005-01-04 devnull if((b = Bopen(name, OREAD)) == nil) {
150 24c02865 2005-01-04 devnull werrstr("Bopen: %r");
151 24c02865 2005-01-04 devnull return -1;
152 24c02865 2005-01-04 devnull }
153 24c02865 2005-01-04 devnull
154 24c02865 2005-01-04 devnull if(Bread(b, xbuf, sizeof xbuf) != sizeof xbuf) {
155 24c02865 2005-01-04 devnull werrstr("short read: %r");
156 24c02865 2005-01-04 devnull return -1;
157 24c02865 2005-01-04 devnull }
158 24c02865 2005-01-04 devnull Bterm(b);
159 24c02865 2005-01-04 devnull buf = xbuf;
160 24c02865 2005-01-04 devnull nbuf = sizeof xbuf;
161 24c02865 2005-01-04 devnull }
162 24c02865 2005-01-04 devnull
163 24c02865 2005-01-04 devnull
164 24c02865 2005-01-04 devnull gfx->g = erealloc(gfx->g, (doc->npage+1)*(sizeof(*gfx->g)));
165 24c02865 2005-01-04 devnull g = &gfx->g[doc->npage];
166 24c02865 2005-01-04 devnull
167 24c02865 2005-01-04 devnull memset(g, 0, sizeof *g);
168 24c02865 2005-01-04 devnull if(memcmp(buf, "GIF", 3) == 0)
169 24c02865 2005-01-04 devnull g->type = Igif;
170 24c02865 2005-01-04 devnull else if(memcmp(buf, "\111\111\052\000", 4) == 0)
171 24c02865 2005-01-04 devnull g->type = Itiff;
172 24c02865 2005-01-04 devnull else if(memcmp(buf, "\115\115\000\052", 4) == 0)
173 24c02865 2005-01-04 devnull g->type = Itiff;
174 24c02865 2005-01-04 devnull else if(memcmp(buf, "\377\330\377", 3) == 0)
175 24c02865 2005-01-04 devnull g->type = Ijpeg;
176 24c02865 2005-01-04 devnull else if(memcmp(buf, "\211PNG\r\n\032\n", 3) == 0)
177 24c02865 2005-01-04 devnull g->type = Ipng;
178 24c02865 2005-01-04 devnull else if(memcmp(buf, "compressed\n", 11) == 0)
179 24c02865 2005-01-04 devnull g->type = Iinferno;
180 24c02865 2005-01-04 devnull else if(memcmp(buf, "\0PC Research, Inc", 17) == 0)
181 24c02865 2005-01-04 devnull g->type = Ifax;
182 24c02865 2005-01-04 devnull else if(memcmp(buf, "TYPE=ccitt-g31", 14) == 0)
183 24c02865 2005-01-04 devnull g->type = Ifax;
184 24c02865 2005-01-04 devnull else if(memcmp(buf, "II*", 3) == 0)
185 24c02865 2005-01-04 devnull g->type = Ifax;
186 24c02865 2005-01-04 devnull else if(memcmp(buf, "TYPE=ccitt-g4", 13) == 0)
187 24c02865 2005-01-04 devnull g->type = Iccittg4;
188 24c02865 2005-01-04 devnull else if(memcmp(buf, "TYPE=", 5) == 0)
189 24c02865 2005-01-04 devnull g->type = Ipic;
190 24c02865 2005-01-04 devnull else if(buf[0] == 'P' && '0' <= buf[1] && buf[1] <= '9')
191 24c02865 2005-01-04 devnull g->type = Ippm;
192 24c02865 2005-01-04 devnull else if(memcmp(buf, "BM", 2) == 0)
193 24c02865 2005-01-04 devnull g->type = Ibmp;
194 24c02865 2005-01-04 devnull else if(memcmp(buf, " ", 10) == 0 &&
195 24c02865 2005-01-04 devnull '0' <= buf[10] && buf[10] <= '9' &&
196 24c02865 2005-01-04 devnull buf[11] == ' ')
197 24c02865 2005-01-04 devnull g->type = Iplan9bm;
198 24c02865 2005-01-04 devnull else if(strtochan((char*)buf) != 0)
199 24c02865 2005-01-04 devnull g->type = Iplan9bm;
200 24c02865 2005-01-04 devnull else if (l > 4 && strcmp(name + l -4, ".yuv") == 0)
201 24c02865 2005-01-04 devnull g->type = Iyuv;
202 24c02865 2005-01-04 devnull else
203 24c02865 2005-01-04 devnull g->type = Icvt2pic;
204 24c02865 2005-01-04 devnull
205 24c02865 2005-01-04 devnull if(name)
206 24c02865 2005-01-04 devnull g->name = estrdup(name);
207 24c02865 2005-01-04 devnull else{
208 24c02865 2005-01-04 devnull g->name = estrdup("stdin"); /* so it can be freed */
209 24c02865 2005-01-04 devnull g->buf = buf;
210 24c02865 2005-01-04 devnull g->nbuf = nbuf;
211 24c02865 2005-01-04 devnull }
212 24c02865 2005-01-04 devnull
213 24c02865 2005-01-04 devnull if(chatty) fprint(2, "classified \"%s\" as \"%s\"\n", g->name, cvt[g->type].name);
214 24c02865 2005-01-04 devnull return doc->npage++;
215 24c02865 2005-01-04 devnull }
216 24c02865 2005-01-04 devnull
217 24c02865 2005-01-04 devnull static int
218 24c02865 2005-01-04 devnull addpage(Document *doc, char *name)
219 24c02865 2005-01-04 devnull {
220 24c02865 2005-01-04 devnull return genaddpage(doc, name, nil, 0);
221 24c02865 2005-01-04 devnull }
222 24c02865 2005-01-04 devnull
223 24c02865 2005-01-04 devnull static int
224 24c02865 2005-01-04 devnull rmpage(Document *doc, int n)
225 24c02865 2005-01-04 devnull {
226 24c02865 2005-01-04 devnull int i;
227 24c02865 2005-01-04 devnull GfxInfo *gfx;
228 24c02865 2005-01-04 devnull
229 24c02865 2005-01-04 devnull if(n < 0 || n >= doc->npage)
230 24c02865 2005-01-04 devnull return -1;
231 24c02865 2005-01-04 devnull
232 24c02865 2005-01-04 devnull gfx = doc->extra;
233 24c02865 2005-01-04 devnull doc->npage--;
234 24c02865 2005-01-04 devnull free(gfx->g[n].name);
235 24c02865 2005-01-04 devnull
236 24c02865 2005-01-04 devnull for(i=n; i<doc->npage; i++)
237 24c02865 2005-01-04 devnull gfx->g[i] = gfx->g[i+1];
238 24c02865 2005-01-04 devnull
239 24c02865 2005-01-04 devnull if(n < doc->npage)
240 24c02865 2005-01-04 devnull return n;
241 24c02865 2005-01-04 devnull if(n == 0)
242 24c02865 2005-01-04 devnull return 0;
243 24c02865 2005-01-04 devnull return n-1;
244 24c02865 2005-01-04 devnull }
245 24c02865 2005-01-04 devnull
246 24c02865 2005-01-04 devnull
247 24c02865 2005-01-04 devnull static Image*
248 24c02865 2005-01-04 devnull convert(Graphic *g)
249 24c02865 2005-01-04 devnull {
250 24c02865 2005-01-04 devnull int fd;
251 24c02865 2005-01-04 devnull Convert c;
252 24c02865 2005-01-04 devnull char *cmd;
253 24c02865 2005-01-04 devnull char *name, buf[1000];
254 24c02865 2005-01-04 devnull Image *im;
255 24c02865 2005-01-04 devnull int rcspawned = 0;
256 24c02865 2005-01-04 devnull Waitmsg *w;
257 24c02865 2005-01-04 devnull
258 24c02865 2005-01-04 devnull c = cvt[g->type];
259 24c02865 2005-01-04 devnull if(c.cmd == nil) {
260 24c02865 2005-01-04 devnull if(chatty) fprint(2, "no conversion for bitmap \"%s\"...\n", g->name);
261 24c02865 2005-01-04 devnull if(g->buf == nil){ /* not stdin */
262 24c02865 2005-01-04 devnull fd = open(g->name, OREAD);
263 24c02865 2005-01-04 devnull if(fd < 0) {
264 24c02865 2005-01-04 devnull fprint(2, "cannot open file: %r\n");
265 24c02865 2005-01-04 devnull wexits("open");
266 24c02865 2005-01-04 devnull }
267 24c02865 2005-01-04 devnull }else
268 24c02865 2005-01-04 devnull fd = stdinpipe(g->buf, g->nbuf);
269 24c02865 2005-01-04 devnull } else {
270 24c02865 2005-01-04 devnull cmd = c.cmd;
271 24c02865 2005-01-04 devnull if(truecolor && c.truecmd)
272 24c02865 2005-01-04 devnull cmd = c.truecmd;
273 24c02865 2005-01-04 devnull
274 24c02865 2005-01-04 devnull if(g->buf != nil) /* is stdin */
275 24c02865 2005-01-04 devnull name = "";
276 24c02865 2005-01-04 devnull else
277 24c02865 2005-01-04 devnull name = g->name;
278 24c02865 2005-01-04 devnull if(strlen(cmd)+strlen(name) > sizeof buf) {
279 24c02865 2005-01-04 devnull fprint(2, "command too long\n");
280 24c02865 2005-01-04 devnull wexits("convert");
281 24c02865 2005-01-04 devnull }
282 24c02865 2005-01-04 devnull snprint(buf, sizeof buf, cmd, name);
283 24c02865 2005-01-04 devnull if(chatty) fprint(2, "using \"%s\" to convert \"%s\"...\n", buf, g->name);
284 24c02865 2005-01-04 devnull fd = spawnrc(buf, g->buf, g->nbuf);
285 24c02865 2005-01-04 devnull rcspawned++;
286 24c02865 2005-01-04 devnull if(fd < 0) {
287 24c02865 2005-01-04 devnull fprint(2, "cannot spawn converter: %r\n");
288 24c02865 2005-01-04 devnull wexits("convert");
289 24c02865 2005-01-04 devnull }
290 24c02865 2005-01-04 devnull }
291 24c02865 2005-01-04 devnull
292 24c02865 2005-01-04 devnull im = readimage(display, fd, 0);
293 24c02865 2005-01-04 devnull if(im == nil) {
294 24c02865 2005-01-04 devnull fprint(2, "warning: couldn't read image: %r\n");
295 24c02865 2005-01-04 devnull }
296 24c02865 2005-01-04 devnull close(fd);
297 24c02865 2005-01-04 devnull
298 24c02865 2005-01-04 devnull /* for some reason rx doesn't work well with wait */
299 24c02865 2005-01-04 devnull /* for some reason 3to1 exits on success with a non-null status of |3to1 */
300 24c02865 2005-01-04 devnull if(rcspawned && g->type != Iccittg4) {
301 24c02865 2005-01-04 devnull if((w=wait())!=nil && w->msg[0] && !strstr(w->msg, "3to1"))
302 24c02865 2005-01-04 devnull fprint(2, "slave wait error: %s\n", w->msg);
303 24c02865 2005-01-04 devnull free(w);
304 24c02865 2005-01-04 devnull }
305 24c02865 2005-01-04 devnull return im;
306 24c02865 2005-01-04 devnull }
307 24c02865 2005-01-04 devnull
308 24c02865 2005-01-04 devnull static int
309 24c02865 2005-01-04 devnull spawnrc(char *cmd, uchar *stdinbuf, int nstdinbuf)
310 24c02865 2005-01-04 devnull {
311 24c02865 2005-01-04 devnull int pfd[2];
312 24c02865 2005-01-04 devnull int pid;
313 24c02865 2005-01-04 devnull
314 24c02865 2005-01-04 devnull if(chatty) fprint(2, "spawning(%s)...", cmd);
315 24c02865 2005-01-04 devnull
316 24c02865 2005-01-04 devnull if(pipe(pfd) < 0)
317 24c02865 2005-01-04 devnull return -1;
318 24c02865 2005-01-04 devnull if((pid = fork()) < 0)
319 24c02865 2005-01-04 devnull return -1;
320 24c02865 2005-01-04 devnull
321 24c02865 2005-01-04 devnull if(pid == 0) {
322 24c02865 2005-01-04 devnull close(pfd[1]);
323 24c02865 2005-01-04 devnull if(stdinbuf)
324 24c02865 2005-01-04 devnull dup(stdinpipe(stdinbuf, nstdinbuf), 0);
325 24c02865 2005-01-04 devnull else
326 24c02865 2005-01-04 devnull dup(open("/dev/null", OREAD), 0);
327 24c02865 2005-01-04 devnull dup(pfd[0], 1);
328 cbeb0b26 2006-04-01 devnull /*dup(pfd[0], 2); */
329 24c02865 2005-01-04 devnull execl("/bin/rc", "rc", "-c", cmd, nil);
330 24c02865 2005-01-04 devnull wexits("exec");
331 24c02865 2005-01-04 devnull }
332 24c02865 2005-01-04 devnull close(pfd[0]);
333 24c02865 2005-01-04 devnull return pfd[1];
334 24c02865 2005-01-04 devnull }
335 24c02865 2005-01-04 devnull