1 /**
2 * Copyright (C) 2001-2002 Artifex Software, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 **/
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "ijs.h"
29 #include "ijs_server.h"
30
31 #define BUF_SIZE 4096
32
33 typedef struct _ExampleParamList ExampleParamList;
34
35 struct _ExampleParamList {
36 ExampleParamList *next;
37 char *key;
38 char *value;
39 int value_size;
40 };
41
42 static int
example_status_cb(void * status_cb_data,IjsServerCtx * ctx,IjsJobId job_id)43 example_status_cb (void *status_cb_data,
44 IjsServerCtx *ctx,
45 IjsJobId job_id)
46 {
47 return 0;
48 }
49
50 static int
example_list_cb(void * list_cb_data,IjsServerCtx * ctx,IjsJobId job_id,char * val_buf,int val_size)51 example_list_cb (void *list_cb_data,
52 IjsServerCtx *ctx,
53 IjsJobId job_id,
54 char *val_buf,
55 int val_size)
56 {
57 const char *param_list = "OutputFile,DeviceManufacturer,DeviceModel,PageImageFormat,Dpi,Width,Height,BitsPerSample,ColorSpace,NumChan,PaperSize,PrintableArea,PrintableTopLeft,TopLeft";
58 int size = strlen (param_list);
59
60 fprintf (stderr, "example_list_cb\n");
61
62 if (size > val_size)
63 return IJS_EBUF;
64
65 memcpy (val_buf, param_list, size);
66 return size;
67 }
68
69 static int
example_enum_cb(void * enum_cb_data,IjsServerCtx * ctx,IjsJobId job_id,const char * key,char * val_buf,int val_size)70 example_enum_cb (void *enum_cb_data,
71 IjsServerCtx *ctx,
72 IjsJobId job_id,
73 const char *key,
74 char *val_buf,
75 int val_size)
76 {
77 const char *val = NULL;
78 if (!strcmp (key, "ColorSpace"))
79 val = "DeviceRGB,DeviceGray,DeviceCMYK";
80 else if (!strcmp (key, "DeviceManufacturer"))
81 val = "IJS Distribution";
82 else if (!strcmp (key, "DeviceModel"))
83 val = "ijs_server_example";
84 else if (!strcmp (key, "PageImageFormat"))
85 val = "Raster";
86
87 if (val == NULL)
88 return IJS_EUNKPARAM;
89 else
90 {
91 int size = strlen (val);
92
93 if (size > val_size)
94 return IJS_EBUF;
95 memcpy (val_buf, val, size);
96 return size;
97 }
98 }
99
100 /* A C implementation of /^(\d\.+\-eE)+x(\d\.+\-eE)+$/ */
101 static int
example_parse_wxh(const char * val,int size,double * pw,double * ph)102 example_parse_wxh (const char *val, int size,
103 double *pw, double *ph)
104 {
105 char buf[256];
106 char *tail;
107 int i;
108
109 for (i = 0; i < size; i++)
110 if (val[i] == 'x')
111 break;
112
113 if (i + 1 >= size)
114 return IJS_ESYNTAX;
115
116 if (i >= sizeof(buf))
117 return IJS_EBUF;
118
119 memcpy (buf, val, i);
120 buf[i] = 0;
121 *pw = strtod (buf, &tail);
122 if (tail == buf)
123 return IJS_ESYNTAX;
124
125 if (size - i > sizeof(buf))
126 return IJS_EBUF;
127
128 memcpy (buf, val + i + 1, size - i - 1);
129 buf[size - i - 1] = 0;
130 *ph = strtod (buf, &tail);
131 if (tail == buf)
132 return IJS_ESYNTAX;
133
134 return 0;
135 }
136
137 /**
138 * example_find_key: Search parameter list for key.
139 *
140 * @key: key to look up
141 *
142 * Return value: ExampleParamList entry matching @key, or NULL.
143 **/
144 static ExampleParamList *
example_find_key(ExampleParamList * pl,const char * key)145 example_find_key (ExampleParamList *pl, const char *key)
146 {
147 ExampleParamList *curs;
148
149 for (curs = pl; curs != NULL; curs = curs->next)
150 {
151 if (!strcmp (curs->key, key))
152 return curs;
153 }
154 return NULL;
155 }
156
157 /**
158 * @printable: An array in which to store the printable area.
159 *
160 * On return, @printable = PrintableArea[0:1] + TopLeft[0:1]
161 **/
162 static int
example_compute_printable(ExampleParamList * pl,double printable[4])163 example_compute_printable (ExampleParamList *pl, double printable[4])
164 {
165 ExampleParamList *curs;
166 double width, height;
167 int code;
168 double margin = 0.5;
169
170 curs = example_find_key (pl, "PaperSize");
171 if (curs == NULL)
172 return -1;
173 code = example_parse_wxh (curs->value, curs->value_size, &width, &height);
174
175 if (code == 0)
176 {
177 printable[0] = width - 2 * margin;
178 printable[1] = height - 2 * margin;
179 printable[2] = margin;
180 printable[3] = margin;
181 }
182
183 return code;
184 }
185
186 static int
example_compute_offset(ExampleParamList * pl,IjsPageHeader * ph,double * px0,double * py0)187 example_compute_offset (ExampleParamList *pl, IjsPageHeader *ph,
188 double *px0, double *py0)
189 {
190 ExampleParamList *curs;
191 double width, height;
192 double top, left;
193 int code;
194
195 *px0 = 0;
196 *py0 = 0;
197
198 curs = example_find_key (pl, "PaperSize");
199 if (curs == NULL)
200 return -1;
201
202 code = example_parse_wxh (curs->value, curs->value_size, &width, &height);
203
204 if (code == 0)
205 {
206 curs = example_find_key (pl, "TopLeft");
207 if (curs != NULL)
208 {
209 code = example_parse_wxh (curs->value, curs->value_size,
210 &top, &left);
211 }
212 else
213 {
214 double printable[4];
215
216 code = example_compute_printable (pl, printable);
217 if (code == 0)
218 {
219 top = printable[2];
220 left = printable[3];
221 }
222 }
223 }
224
225 if (code == 0)
226 {
227 *px0 = left;
228 *py0 = height - ph->height / ph->yres - top;
229 }
230
231 return code;
232 }
233
234 static int
example_get_cb(void * get_cb_data,IjsServerCtx * ctx,IjsJobId job_id,const char * key,char * val_buf,int val_size)235 example_get_cb (void *get_cb_data,
236 IjsServerCtx *ctx,
237 IjsJobId job_id,
238 const char *key,
239 char *val_buf,
240 int val_size)
241 {
242 ExampleParamList *pl = *(ExampleParamList **)get_cb_data;
243 ExampleParamList *curs;
244 const char *val;
245 char buf[256];
246 int code;
247
248 fprintf (stderr, "example_get_cb: %s\n", key);
249 curs = example_find_key (pl, key);
250 if (curs != NULL)
251 {
252 if (curs->value_size > val_size)
253 return IJS_EBUF;
254 memcpy (val_buf, curs->value, curs->value_size);
255 return curs->value_size;
256 }
257
258 if (!strcmp (key, "PrintableArea") || !strcmp (key, "PrintableTopLeft"))
259 {
260 double printable[4];
261 int off = !strcmp (key, "PrintableArea") ? 0 : 2;
262
263 code = example_compute_printable (pl, printable);
264 if (code == 0)
265 {
266 sprintf (buf, "%gx%g", printable[off + 0], printable[off + 1]);
267 val = buf;
268 }
269 }
270
271 if (!strcmp (key, "DeviceManufacturer"))
272 val = "IJS Distribution";
273 else if (!strcmp (key, "DeviceModel"))
274 val = "ijs_server_example";
275 else if (!strcmp (key, "PageImageFormat"))
276 val = "Raster";
277
278 if (val == NULL)
279 return IJS_EUNKPARAM;
280 else
281 {
282 int size = strlen (val);
283
284 if (size > val_size)
285 return IJS_EBUF;
286 memcpy (val_buf, val, size);
287 return size;
288 }
289 }
290
291 static int
example_set_cb(void * set_cb_data,IjsServerCtx * ctx,IjsJobId job_id,const char * key,const char * value,int value_size)292 example_set_cb (void *set_cb_data, IjsServerCtx *ctx, IjsJobId job_id,
293 const char *key, const char *value, int value_size)
294 {
295 ExampleParamList **ppl = (ExampleParamList **)set_cb_data;
296 ExampleParamList *pl;
297 int key_len = strlen (key);
298 int code;
299
300 fprintf (stderr, "example_set_cb: %s=", key);
301
302 if (!strcmp (key, "PaperSize"))
303 {
304 double width, height;
305
306 code = example_parse_wxh (value, value_size, &width, &height);
307 if (code < 0)
308 return code;
309 }
310
311 fwrite (value, 1, value_size, stderr);
312 fputs ("\n", stderr);
313
314 pl = example_find_key (*ppl, key);
315
316 if (pl == NULL)
317 {
318 pl = (ExampleParamList *)malloc (sizeof (ExampleParamList));
319 pl->next = *ppl;
320 pl->key = malloc (key_len + 1);
321 memcpy (pl->key, key, key_len + 1);
322 *ppl = pl;
323 }
324 else
325 {
326 free (pl->value);
327 }
328
329 pl->value = malloc (value_size);
330 memcpy (pl->value, value, value_size);
331 pl->value_size = value_size;
332 return 0;
333 }
334
335 /**
336 * Finds a parameter in the param list, and allocates a null terminated
337 * string with the value.
338 **/
339 static char *
find_param(ExampleParamList * pl,const char * key)340 find_param (ExampleParamList *pl, const char *key)
341 {
342 ExampleParamList *curs;
343 char *result;
344
345 curs = example_find_key (pl, key);
346 if (curs == NULL)
347 return NULL;
348
349 result = malloc (curs->value_size + 1);
350 memcpy (result, curs->value, curs->value_size);
351 result[curs->value_size] = 0;
352 return result;
353 }
354
355 static void
free_param_list(ExampleParamList * pl)356 free_param_list (ExampleParamList *pl)
357 {
358 ExampleParamList *next;
359
360 for (; pl != NULL; pl = next)
361 {
362 next = pl->next;
363 free (pl->key);
364 free (pl->value);
365 free (pl);
366 }
367 }
368
369 int
main(int argc,char ** argv)370 main (int argc, char **argv)
371 {
372 IjsServerCtx *ctx;
373 IjsPageHeader ph;
374 int status;
375 char buf[BUF_SIZE];
376 char hexbuf[BUF_SIZE * 3];
377 char *fn;
378 FILE *f = NULL;
379 double xscale, yscale;
380 double x0, y0;
381 ExampleParamList *pl = NULL;
382
383 ctx = ijs_server_init ();
384 if (ctx == NULL)
385 return (1);
386 ijs_server_install_status_cb (ctx, example_status_cb, &pl);
387 ijs_server_install_list_cb (ctx, example_list_cb, &pl);
388 ijs_server_install_enum_cb (ctx, example_enum_cb, &pl);
389 ijs_server_install_set_cb (ctx, example_set_cb, &pl);
390 ijs_server_install_get_cb (ctx, example_get_cb, &pl);
391
392 do
393 {
394 int total_bytes, bytes_left;
395 ExampleParamList *curs;
396
397 status = ijs_server_get_page_header (ctx, &ph);
398 if (status) break;
399 fprintf (stderr, "got page header, %d x %d\n",
400 ph.width, ph.height);
401
402 if (f == NULL)
403 {
404 fn = find_param (pl, "OutputFile");
405 /* todo: check error! */
406
407 if (fn == NULL)
408 {
409 fn = find_param (pl, "OutputFD");
410 if (fn != NULL)
411 {
412 f = fdopen (atoi (fn), "w");
413 }
414 }
415 else
416 {
417 f = fopen (fn, "w");
418 }
419 if (f == NULL)
420 {
421 fprintf (stderr, "can't open output file %s\n", fn);
422 fclose (stdin);
423 fclose (stdout);
424 break;
425 }
426 if (fn != NULL)
427 free (fn);
428 }
429
430 fprintf (f, "%%!PS-Adobe-2.0\n");
431
432 example_compute_offset (pl, &ph, &x0, &y0);
433
434 xscale = 72.0 / ph.xres;
435 yscale = 72.0 / ph.yres;
436
437 fprintf (f, "%%%%BoundingBox: %d %d %d %d\n",
438 (int)(x0 * 72), (int)(y0 * 72),
439 (int)(x0 * 72 + xscale * ph.width + 0.999),
440 (int)(y0 * 72 + yscale * ph.height + 0.999));
441
442 fprintf (f, "/rhex { currentfile exch readhexstring pop } bind def\n");
443 fprintf (f, "/picstr %d string def\n", ph.width);
444
445 for (curs = pl; curs != NULL; curs = curs->next)
446 {
447 fprintf (f, "%% IJS parameter: %s = ", curs->key);
448 fwrite (curs->value, 1, curs->value_size, f);
449 fputs ("\n", f);
450 }
451
452 fprintf (f,
453 "gsave\n"
454 "%f %f translate\n"
455 "%f %f scale\n"
456 "%d %d %d\n"
457 "[ %d 0 0 %d 0 %d ]\n",
458 x0 * 72, y0 * 72,
459 xscale * ph.width, yscale * ph.height,
460 ph.width, ph.height, ph.bps,
461 ph.width, -ph.height, ph.height);
462 if (ph.n_chan == 1)
463 fprintf (f, "{ picstr rhex } image\n");
464 else
465 {
466 fprintf (f, "{ picstr rhex }\n"
467 "false %d colorimage\n", ph.n_chan);
468 }
469 total_bytes = ((ph.n_chan * ph.bps * ph.width + 7) >> 3) * ph.height;
470 bytes_left = total_bytes;
471 while (bytes_left)
472 {
473 int n_bytes = bytes_left;
474 int i, j;
475
476 if (n_bytes > sizeof(buf))
477 n_bytes = sizeof(buf);
478 #ifdef VERBOSE
479 fprintf (stderr, "%d bytes left, reading %d\n", bytes_left, n_bytes);
480 #endif
481 status = ijs_server_get_data (ctx, buf, n_bytes);
482 if (status)
483 {
484 fprintf (stderr, "page aborted!\n");
485 break;
486 }
487 j = 0;
488 for (i = 0; i < n_bytes; i++)
489 {
490 const char hex[16] = "0123456789AbCdEf";
491 unsigned char c = ((unsigned char *)buf)[i];
492
493 hexbuf[j++] = hex[c >> 4];
494 hexbuf[j++] = hex[c & 0xf];
495 if ((i & 31) == 31)
496 hexbuf[j++] = '\n';
497 }
498 if ((n_bytes & 31) != 0)
499 hexbuf[j++] = '\n';
500 fwrite (hexbuf, 1, j, f);
501 bytes_left -= n_bytes;
502 }
503 fprintf (f, "grestore\nshowpage\n");
504 }
505 while (status == 0);
506
507 if (status > 0) status = 0; /* normal exit */
508
509 if (f)
510 fclose (f);
511 ijs_server_done (ctx);
512
513 free_param_list (pl);
514
515 #ifdef VERBOSE
516 fprintf (stderr, "server exiting with status %d\n", status);
517 #endif
518 return status;
519 }
520