summaryrefslogtreecommitdiff
path: root/ijs_server_example.c
diff options
context:
space:
mode:
Diffstat (limited to 'ijs_server_example.c')
-rw-r--r--ijs_server_example.c519
1 files changed, 519 insertions, 0 deletions
diff --git a/ijs_server_example.c b/ijs_server_example.c
new file mode 100644
index 0000000..477af66
--- /dev/null
+++ b/ijs_server_example.c
@@ -0,0 +1,519 @@
+/**
+ * Copyright (c) 2001-2002 artofcode LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+**/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ijs.h"
+#include "ijs_server.h"
+
+#define BUF_SIZE 4096
+
+typedef struct _ExampleParamList ExampleParamList;
+
+struct _ExampleParamList {
+ ExampleParamList *next;
+ char *key;
+ char *value;
+ int value_size;
+};
+
+static int
+example_status_cb (void *status_cb_data,
+ IjsServerCtx *ctx,
+ IjsJobId job_id)
+{
+ return 0;
+}
+
+static int
+example_list_cb (void *list_cb_data,
+ IjsServerCtx *ctx,
+ IjsJobId job_id,
+ char *val_buf,
+ int val_size)
+{
+ const char *param_list = "OutputFile,DeviceManufacturer,DeviceModel,PageImageFormat,Dpi,Width,Height,BitsPerSample,ColorSpace,NumChan,PaperSize,PrintableArea,PrintableTopLeft,TopLeft";
+ int size = strlen (param_list);
+
+ fprintf (stderr, "example_list_cb\n");
+
+ if (size > val_size)
+ return IJS_EBUF;
+
+ memcpy (val_buf, param_list, size);
+ return size;
+}
+
+static int
+example_enum_cb (void *enum_cb_data,
+ IjsServerCtx *ctx,
+ IjsJobId job_id,
+ const char *key,
+ char *val_buf,
+ int val_size)
+{
+ const char *val = NULL;
+ if (!strcmp (key, "ColorSpace"))
+ val = "DeviceRGB,DeviceGray,DeviceCMYK";
+ else if (!strcmp (key, "DeviceManufacturer"))
+ val = "IJS Distribution";
+ else if (!strcmp (key, "DeviceModel"))
+ val = "ijs_server_example";
+ else if (!strcmp (key, "PageImageFormat"))
+ val = "Raster";
+
+ if (val == NULL)
+ return IJS_EUNKPARAM;
+ else
+ {
+ int size = strlen (val);
+
+ if (size > val_size)
+ return IJS_EBUF;
+ memcpy (val_buf, val, size);
+ return size;
+ }
+}
+
+/* A C implementation of /^(\d\.+\-eE)+x(\d\.+\-eE)+$/ */
+static int
+example_parse_wxh (const char *val, int size,
+ double *pw, double *ph)
+{
+ char buf[256];
+ char *tail;
+ int i;
+
+ for (i = 0; i < size; i++)
+ if (val[i] == 'x')
+ break;
+
+ if (i + 1 >= size)
+ return IJS_ESYNTAX;
+
+ if (i >= sizeof(buf))
+ return IJS_EBUF;
+
+ memcpy (buf, val, i);
+ buf[i] = 0;
+ *pw = strtod (buf, &tail);
+ if (tail == buf)
+ return IJS_ESYNTAX;
+
+ if (size - i > sizeof(buf))
+ return IJS_EBUF;
+
+ memcpy (buf, val + i + 1, size - i - 1);
+ buf[size - i - 1] = 0;
+ *ph = strtod (buf, &tail);
+ if (tail == buf)
+ return IJS_ESYNTAX;
+
+ return 0;
+}
+
+/**
+ * example_find_key: Search parameter list for key.
+ *
+ * @key: key to look up
+ *
+ * Return value: ExampleParamList entry matching @key, or NULL.
+ **/
+static ExampleParamList *
+example_find_key (ExampleParamList *pl, const char *key)
+{
+ ExampleParamList *curs;
+
+ for (curs = pl; curs != NULL; curs = curs->next)
+ {
+ if (!strcmp (curs->key, key))
+ return curs;
+ }
+ return NULL;
+}
+
+/**
+ * @printable: An array in which to store the printable area.
+ *
+ * On return, @printable = PrintableArea[0:1] + TopLeft[0:1]
+ **/
+static int
+example_compute_printable (ExampleParamList *pl, double printable[4])
+{
+ ExampleParamList *curs;
+ double width, height;
+ int code;
+ double margin = 0.5;
+
+ curs = example_find_key (pl, "PaperSize");
+ if (curs == NULL)
+ return -1;
+ code = example_parse_wxh (curs->value, curs->value_size, &width, &height);
+
+ if (code == 0)
+ {
+ printable[0] = width - 2 * margin;
+ printable[1] = height - 2 * margin;
+ printable[2] = margin;
+ printable[3] = margin;
+ }
+
+ return code;
+}
+
+static int
+example_compute_offset (ExampleParamList *pl, IjsPageHeader *ph,
+ double *px0, double *py0)
+{
+ ExampleParamList *curs;
+ double width, height;
+ double top, left;
+ int code;
+
+ *px0 = 0;
+ *py0 = 0;
+
+ curs = example_find_key (pl, "PaperSize");
+ if (curs == NULL)
+ return -1;
+
+ code = example_parse_wxh (curs->value, curs->value_size, &width, &height);
+
+ if (code == 0)
+ {
+ curs = example_find_key (pl, "TopLeft");
+ if (curs != NULL)
+ {
+ code = example_parse_wxh (curs->value, curs->value_size,
+ &top, &left);
+ }
+ else
+ {
+ double printable[4];
+
+ code = example_compute_printable (pl, printable);
+ if (code == 0)
+ {
+ top = printable[2];
+ left = printable[3];
+ }
+ }
+ }
+
+ if (code == 0)
+ {
+ *px0 = left;
+ *py0 = height - ph->height / ph->yres - top;
+ }
+
+ return code;
+}
+
+static int
+example_get_cb (void *get_cb_data,
+ IjsServerCtx *ctx,
+ IjsJobId job_id,
+ const char *key,
+ char *val_buf,
+ int val_size)
+{
+ ExampleParamList *pl = *(ExampleParamList **)get_cb_data;
+ ExampleParamList *curs;
+ const char *val;
+ char buf[256];
+ int code;
+
+ fprintf (stderr, "example_get_cb: %s\n", key);
+ curs = example_find_key (pl, key);
+ if (curs != NULL)
+ {
+ if (curs->value_size > val_size)
+ return IJS_EBUF;
+ memcpy (val_buf, curs->value, curs->value_size);
+ return curs->value_size;
+ }
+
+ if (!strcmp (key, "PrintableArea") || !strcmp (key, "PrintableTopLeft"))
+ {
+ double printable[4];
+ int off = !strcmp (key, "PrintableArea") ? 0 : 2;
+
+ code = example_compute_printable (pl, printable);
+ if (code == 0)
+ {
+ sprintf (buf, "%gx%g", printable[off + 0], printable[off + 1]);
+ val = buf;
+ }
+ }
+
+ if (!strcmp (key, "DeviceManufacturer"))
+ val = "IJS Distribution";
+ else if (!strcmp (key, "DeviceModel"))
+ val = "ijs_server_example";
+ else if (!strcmp (key, "PageImageFormat"))
+ val = "Raster";
+
+ if (val == NULL)
+ return IJS_EUNKPARAM;
+ else
+ {
+ int size = strlen (val);
+
+ if (size > val_size)
+ return IJS_EBUF;
+ memcpy (val_buf, val, size);
+ return size;
+ }
+}
+
+static int
+example_set_cb (void *set_cb_data, IjsServerCtx *ctx, IjsJobId job_id,
+ const char *key, const char *value, int value_size)
+{
+ ExampleParamList **ppl = (ExampleParamList **)set_cb_data;
+ ExampleParamList *pl;
+ int key_len = strlen (key);
+ int code;
+
+ fprintf (stderr, "example_set_cb: %s=", key);
+
+ if (!strcmp (key, "PaperSize"))
+ {
+ double width, height;
+
+ code = example_parse_wxh (value, value_size, &width, &height);
+ if (code < 0)
+ return code;
+ }
+
+ fwrite (value, 1, value_size, stderr);
+ fputs ("\n", stderr);
+
+ pl = example_find_key (*ppl, key);
+
+ if (pl == NULL)
+ {
+ pl = (ExampleParamList *)malloc (sizeof (ExampleParamList));
+ pl->next = *ppl;
+ pl->key = malloc (key_len + 1);
+ memcpy (pl->key, key, key_len + 1);
+ *ppl = pl;
+ }
+ else
+ {
+ free (pl->value);
+ }
+
+ pl->value = malloc (value_size);
+ memcpy (pl->value, value, value_size);
+ pl->value_size = value_size;
+ return 0;
+}
+
+/**
+ * Finds a parameter in the param list, and allocates a null terminated
+ * string with the value.
+ **/
+static char *
+find_param (ExampleParamList *pl, const char *key)
+{
+ ExampleParamList *curs;
+ char *result;
+
+ curs = example_find_key (pl, key);
+ if (curs == NULL)
+ return NULL;
+
+ result = malloc (curs->value_size + 1);
+ memcpy (result, curs->value, curs->value_size);
+ result[curs->value_size] = 0;
+ return result;
+}
+
+static void
+free_param_list (ExampleParamList *pl)
+{
+ ExampleParamList *next;
+
+ for (; pl != NULL; pl = next)
+ {
+ next = pl->next;
+ free (pl->key);
+ free (pl->value);
+ free (pl);
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ IjsServerCtx *ctx;
+ IjsPageHeader ph;
+ int status;
+ char buf[BUF_SIZE];
+ char hexbuf[BUF_SIZE * 3];
+ char *fn;
+ FILE *f = NULL;
+ double xscale, yscale;
+ double x0, y0;
+ ExampleParamList *pl = NULL;
+
+ ctx = ijs_server_init ();
+ if (ctx == NULL)
+ return (1);
+ ijs_server_install_status_cb (ctx, example_status_cb, &pl);
+ ijs_server_install_list_cb (ctx, example_list_cb, &pl);
+ ijs_server_install_enum_cb (ctx, example_enum_cb, &pl);
+ ijs_server_install_set_cb (ctx, example_set_cb, &pl);
+ ijs_server_install_get_cb (ctx, example_get_cb, &pl);
+
+ do
+ {
+ int total_bytes, bytes_left;
+ ExampleParamList *curs;
+
+ status = ijs_server_get_page_header (ctx, &ph);
+ if (status) break;
+ fprintf (stderr, "got page header, %d x %d\n",
+ ph.width, ph.height);
+
+ if (f == NULL)
+ {
+ fn = find_param (pl, "OutputFile");
+ /* todo: check error! */
+
+ if (fn == NULL)
+ {
+ fn = find_param (pl, "OutputFD");
+ if (fn != NULL)
+ {
+ f = fdopen (atoi (fn), "w");
+ }
+ }
+ else
+ {
+ f = fopen (fn, "w");
+ }
+ if (f == NULL)
+ {
+ fprintf (stderr, "can't open output file %s\n", fn);
+ fclose (stdin);
+ fclose (stdout);
+ break;
+ }
+ if (fn != NULL)
+ free (fn);
+ }
+
+ fprintf (f, "%%!PS-Adobe-2.0\n");
+
+ example_compute_offset (pl, &ph, &x0, &y0);
+
+ xscale = 72.0 / ph.xres;
+ yscale = 72.0 / ph.yres;
+
+ fprintf (f, "%%%%BoundingBox: %d %d %d %d\n",
+ (int)(x0 * 72), (int)(y0 * 72),
+ (int)(x0 * 72 + xscale * ph.width + 0.999),
+ (int)(y0 * 72 + yscale * ph.height + 0.999));
+
+ fprintf (f, "/rhex { currentfile exch readhexstring pop } bind def\n");
+ fprintf (f, "/picstr %d string def\n", ph.width);
+
+ for (curs = pl; curs != NULL; curs = curs->next)
+ {
+ fprintf (f, "%% IJS parameter: %s = ", curs->key);
+ fwrite (curs->value, 1, curs->value_size, f);
+ fputs ("\n", f);
+ }
+
+ fprintf (f,
+ "gsave\n"
+ "%f %f translate\n"
+ "%f %f scale\n"
+ "%d %d %d\n"
+ "[ %d 0 0 %d 0 %d ]\n",
+ x0 * 72, y0 * 72,
+ xscale * ph.width, yscale * ph.height,
+ ph.width, ph.height, ph.bps,
+ ph.width, -ph.height, ph.height);
+ if (ph.n_chan == 1)
+ fprintf (f, "{ picstr rhex } image\n");
+ else
+ {
+ fprintf (f, "{ picstr rhex }\n"
+ "false %d colorimage\n", ph.n_chan);
+ }
+ total_bytes = ((ph.n_chan * ph.bps * ph.width + 7) >> 3) * ph.height;
+ bytes_left = total_bytes;
+ while (bytes_left)
+ {
+ int n_bytes = bytes_left;
+ int i, j;
+
+ if (n_bytes > sizeof(buf))
+ n_bytes = sizeof(buf);
+#ifdef VERBOSE
+ fprintf (stderr, "%d bytes left, reading %d\n", bytes_left, n_bytes);
+#endif
+ status = ijs_server_get_data (ctx, buf, n_bytes);
+ if (status)
+ {
+ fprintf (stderr, "page aborted!\n");
+ break;
+ }
+ j = 0;
+ for (i = 0; i < n_bytes; i++)
+ {
+ const char hex[16] = "0123456789AbCdEf";
+ unsigned char c = ((unsigned char *)buf)[i];
+
+ hexbuf[j++] = hex[c >> 4];
+ hexbuf[j++] = hex[c & 0xf];
+ if ((i & 31) == 31)
+ hexbuf[j++] = '\n';
+ }
+ if ((n_bytes & 31) != 0)
+ hexbuf[j++] = '\n';
+ fwrite (hexbuf, 1, j, f);
+ bytes_left -= n_bytes;
+ }
+ fprintf (f, "grestore\nshowpage\n");
+ }
+ while (status == 0);
+
+ if (status > 0) status = 0; /* normal exit */
+
+ if (f)
+ fclose (f);
+ ijs_server_done (ctx);
+
+ free_param_list (pl);
+
+#ifdef VERBOSE
+ fprintf (stderr, "server exiting with status %d\n", status);
+#endif
+ return status;
+}