/** * Copyright (C) 2001-2021 Artifex Software, Inc. * * 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 #include #include #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), "wb"); } } else { f = fopen (fn, "wb"); } 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; }