1 diff -uNr old/gdevijs.c new/gdevijs.c
2 --- old/gdevijs.c 2008-01-15 20:20:07.000000000 -0800
3 +++ new/gdevijs.c 2008-01-17 09:52:54.000000000 -0800
5 * which is a security risk, since any program can be run.
6 * You should use -dSAFER which sets .LockSafetyParams to true
7 * before opening this device.
9 + * 11/26/03 David Suffield (gdevijs-krgb-1.0.patch)
10 + * (c) 2003-2004 Copyright Hewlett-Packard Development Company, LP
12 + * 1. Removed hpijs 1.0-1.0.2 workarounds, use hpijs 1.0.3 or higher.
13 + * 2. Added krgb support.
15 + * 02/21/05 David Suffield (gdevijs-krgb-1.1.patch)
16 + * 1. Fixed segfault issue with 1-bit color space.
17 + * 2. Fixed z-order issue with colored text on black rectangle.
19 + * 02/22/06 David Suffield (gdevijs-krgb-1.2.patch)
20 + * 1. Fixed krgb buffer overflow issue with out-of-band data in fill_rectangle and copy_mono.
21 + * This buffer overflow condition occurred with fullbleed print jobs that had k-band images.
22 + * 2. Added Dan Coby (artifex) fix for gsijs_read_string_malloc gs_free *str memory leak.
24 + * 06/02/06 David Suffield (gdevijs-krgb-1.3.patch)
25 + * 1. Revisited the krgb buffer overflow issue with out-of-band data in fill_rectangle and
26 + * copy_mono. Changed the fill_rectangle and copy_mono to an inner loop buffer check
27 + * instead of a outer loop x/y extent check.
28 + * 2. As requested by Ralph Giles, added K 1-bit and 8-bit support for krgb, but only 1-bit is
29 + * implemented for now.
32 + * 1. K=1-bit or 8-bit black plane, RGB=24 bit color raster.
33 + * 2. K-plane will only contain objects that are black text and black line drawings.
34 + * 3. RGB raster will not contain K-plane objects.
35 + * 4. K resolution and RGB resolution will be equal.
36 + * 5. K-plane will be byte aligned.
37 + * 6. K-plane 1-bit definition; 1=black, 0=nothing (KRGB).
38 + * 7. K-plane 8-bit definition; 255=black, 0=nothing (KxRGB).
40 + * 1/15/08 David Suffield (gdevijs-krgb-1.5.patch)
41 + * 1. Added checks for null forward device in the graphic procedures.
42 + * 2. Corrected the "force banding" code in gsijs_open. Needed for small images (IE: hagaki in landscape).
46 #include "unistd_.h" /* for dup() */
52 #include "ijs_client.h"
56 /* This should go into gdevprn.h, or, better yet, gdevprn should
57 acquire an API for changing resolution. */
58 int gdev_prn_maybe_realloc_memory(gx_device_printer *pdev,
60 static dev_proc_put_params(gsijs_put_params);
61 static dev_proc_finish_copydevice(gsijs_finish_copydevice);
63 +/* Following definitions are for krgb support. */
64 +static dev_proc_create_buf_device(gsijs_create_buf_device);
65 +static dev_proc_fill_rectangle(gsijs_fill_rectangle);
66 +static dev_proc_copy_mono(gsijs_copy_mono);
67 +static dev_proc_fill_mask(gsijs_fill_mask);
68 +static dev_proc_fill_path(gsijs_fill_path);
69 +static dev_proc_stroke_path(gsijs_stroke_path);
71 static const gx_device_procs gsijs_procs = {
73 NULL, /* get_initial_matrix */
79 + /* Additional parameters for krgb support. */
80 + int krgb_mode; /* 0=false, 1=true */
81 + int k_bits; /* number of bits in k plane, 1 or 8 */
82 + int k_path; /* k plane path, 0=false, 1=true */
83 + int k_width; /* k plane width in pixels */
84 + int k_band_size; /* k plane buffer size in bytes, byte aligned */
85 + unsigned char *k_band; /* k plane buffer */
86 + gx_device_procs prn_procs; /* banding playback procedures */
89 #define DEFAULT_DPI 74 /* See gsijs_set_resolution() below. */
91 FALSE, /* Tumble_set */
93 NULL, /* IjsClient *ctx */
95 + 0, /* ijs_version */
100 + 0, /* k_band_size */
101 + NULL /* k_band buffer */
105 @@ -166,12 +228,314 @@
107 /**************************************************************************/
109 -/* ------ Private definitions ------ */
110 +/* ---------------- Low-level graphic procedures ---------------- */
112 +static unsigned char xmask[] =
124 +static int gsijs_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
125 + gx_color_index color)
127 + gx_device_ijs *ijsdev = (gx_device_ijs *)((gx_device_forward *)dev)->target;
130 + return 0; /* no forward device, bug?? */
132 + if (ijsdev->krgb_mode && ijsdev->k_path && y >= 0 && x >= 0)
134 + int raster = (ijsdev->k_width+7) >> 3;
135 + register unsigned char *dest;
136 + int dest_start_bit;
137 + int band_height = ijsdev->k_band_size/raster;
139 + unsigned char *beg = ijsdev->k_band;
140 + unsigned char *end = ijsdev->k_band+ijsdev->k_band_size;
143 + if (h <= 0 || w <= 0)
146 + /* Check for out-of-band graphic. */
147 + if (x >= ijsdev->k_width || y >= band_height)
148 + return 0; /* out-of-band */
150 + dest_start_bit = x & 7;
151 + dest=ijsdev->k_band+(raster*y)+(x >> 3);
153 + /* Note x,y orgin 0,0 is stored first byte 0 left to right. */
157 + /* Color is black, store in k plane band instead of regular band. */
158 + for (j=0; j<h; j++)
160 + for (i=0; i<w; i++)
162 + p = &dest[(dest_start_bit+i)>>3];
163 + if (p >= beg && p <= end)
164 + *p |= xmask[(dest_start_bit+i)&7];
172 + /* Color is not black, remove any k plane bits for z-order dependencies, store in regular band. */
173 + for (j=0; j<h; j++)
175 + for (i=0; i<w; i++)
177 + p = &dest[(dest_start_bit+i)>>3];
178 + if (p >= beg && p <= end)
179 + *p &= ~xmask[(dest_start_bit+i)&7];
186 + return (*ijsdev->prn_procs.fill_rectangle)(dev, x, y, w, h, color);
189 +static int gsijs_copy_mono(gx_device * dev, const byte * data,
190 + int dx, int draster, gx_bitmap_id id,
191 + int x, int y, int w, int height, gx_color_index zero, gx_color_index one)
193 + gx_device_ijs *ijsdev = (gx_device_ijs *)((gx_device_forward *)dev)->target;
196 + return 0; /* no forward device, bug?? */
198 + // if (ijsdev->krgb_mode && ijsdev->k_path && one==0x0)
199 + if (ijsdev->krgb_mode && ijsdev->k_path)
201 + /* Store in k plane band instead of regular band. */
202 + int raster = (ijsdev->k_width+7) >> 3; /* raster width in bytes, byte aligned */
203 + register unsigned char *dest;
204 + register const unsigned char *scan;
205 + int dest_start_bit;
206 + int scan_start_bit;
207 + int band_height = ijsdev->k_band_size/raster;
209 + unsigned char *beg = ijsdev->k_band;
210 + unsigned char *end = ijsdev->k_band+ijsdev->k_band_size;
213 + if (h <= 0 || w <= 0)
216 + /* Check for out-of-band graphic. */
217 + if (x >= ijsdev->k_width || y >= band_height)
218 + return 0; /* out-of-band */
220 + scan=data+(dx >> 3);
221 + dest_start_bit = x & 7;
222 + scan_start_bit = dx & 7;
223 + dest=ijsdev->k_band+(raster*y)+(x >> 3);
227 + /* Color is black, store in k plane band instead of regular band. */
230 + for (i=0; i<w; i++)
232 + if (scan[(scan_start_bit+i)>>3] & xmask[(scan_start_bit+i)&7])
234 + p = &dest[(dest_start_bit+i)>>3];
235 + if (p >= beg && p <= end)
236 + *p |= xmask[(dest_start_bit+i)&7];
246 + /* Color is not black, remove any k plane bits for z-order dependencies, store in regular band. */
249 + for (i=0; i<w; i++)
251 + if (scan[(scan_start_bit+i)>>3] & xmask[(scan_start_bit+i)&7])
253 + p = &dest[(dest_start_bit+i)>>3];
254 + if (p >= beg && p <= end)
255 + *p &= ~xmask[(dest_start_bit+i)&7];
264 + return (*ijsdev->prn_procs.copy_mono)(dev, data, dx, draster, id, x, y, w, height, zero, one);
267 +/* ---------------- High-level graphic procedures ---------------- */
269 +static int gsijs_fill_mask(gx_device * dev,
270 + const byte * data, int dx, int raster, gx_bitmap_id id,
271 + int x, int y, int w, int h,
272 + const gx_drawing_color * pdcolor, int depth,
273 + gs_logical_operation_t lop, const gx_clip_path * pcpath)
275 + gx_device_ijs *ijsdev = (gx_device_ijs *)((gx_device_forward *)dev)->target;
279 + return 0; /* no forward device, bug?? */
281 + ijsdev->k_path = 1;
283 + code = (*ijsdev->prn_procs.fill_mask)(dev, data, dx, raster, id, x, y, w, h, pdcolor, depth, lop, pcpath);
285 + ijsdev->k_path = 0;
290 +static int gsijs_fill_path(gx_device * dev, const gs_imager_state * pis,
291 + gx_path * ppath, const gx_fill_params * params,
292 + const gx_drawing_color * pdcolor,
293 + const gx_clip_path * pcpath)
295 + gx_device_ijs *ijsdev = (gx_device_ijs *)((gx_device_forward *)dev)->target;
299 + return 0; /* no forward device, bug?? */
301 + ijsdev->k_path = 1;
303 + code = (*ijsdev->prn_procs.fill_path)(dev, pis, ppath, params, pdcolor, pcpath);
305 -/* Versions 1.0 through 1.0.2 of hpijs report IJS version 0.29, and
306 - require some workarounds. When more up-to-date hpijs versions
307 - become ubiquitous, all these workarounds should be removed. */
308 -#define HPIJS_1_0_VERSION 29
309 + ijsdev->k_path = 0;
314 +static int gsijs_stroke_path(gx_device * dev, const gs_imager_state * pis,
315 + gx_path * ppath, const gx_stroke_params * params,
316 + const gx_drawing_color * pdcolor,
317 + const gx_clip_path * pcpath)
319 + gx_device_ijs *ijsdev = (gx_device_ijs *)((gx_device_forward *)dev)->target;
323 + return 0; /* no forward device, bug?? */
325 + ijsdev->k_path = 1;
327 + code = (*ijsdev->prn_procs.stroke_path)(dev, pis, ppath, params, pdcolor, pcpath);
329 + ijsdev->k_path = 0;
334 +/* ---------------- krgb banding playback procedures ---------------- */
336 +static int gsijs_get_bits(gx_device_printer * pdev, int y, byte * str, byte ** actual_data)
338 + gx_device_ijs *ijsdev = (gx_device_ijs *)pdev;
339 + gx_device_clist_common *cdev = (gx_device_clist_common *)pdev;
340 + int band_height = cdev->page_info.band_params.BandHeight;
341 + int band_number = y/band_height;
342 + int raster = (ijsdev->k_width+7) >> 3; /* raster width in bytes, byte aligned */
343 + int y1=raster*(y-(band_height*band_number));
347 + /* First raster for band, clear k_band. Banding playback occurs on first raster. */
348 + memset(ijsdev->k_band, 0, ijsdev->k_band_size);
351 + return gdev_prn_get_bits(pdev, y, str, actual_data); /* get raster from regular band */
354 +static int gsijs_k_get_bits(gx_device_printer * pdev, int y, byte ** actual_data)
356 + gx_device_ijs *ijsdev = (gx_device_ijs *)pdev;
357 + gx_device_clist_common *cdev = (gx_device_clist_common *)pdev;
358 + int band_height = cdev->page_info.band_params.BandHeight;
359 + int band_number = y/band_height;
360 + int raster = (ijsdev->k_width+7) >> 3; /* raster width in bytes, byte aligned */
361 + int y1=raster*(y-(band_height*band_number));
363 + *actual_data = ijsdev->k_band+y1;
368 +static int gsijs_create_buf_device(gx_device **pbdev, gx_device *target,
369 + const gx_render_plane_t *render_plane, gs_memory_t *mem, gx_band_complexity_t *for_band)
371 + gx_device_ijs *ijsdev = (gx_device_ijs *)target;
372 + int n_chan = ijsdev->color_info.num_components;
373 + int code = gx_default_create_buf_device(pbdev, target, render_plane, mem, for_band);
374 + if (code < 0 || n_chan != 3)
377 + /* Save buffer (vector) procedures so that we can hook them during banding playback. */
378 + ijsdev->prn_procs = (*pbdev)->procs;
380 + /* Replace buffer procedures with krgb procedures. */
381 + set_dev_proc(*pbdev, fill_rectangle, gsijs_fill_rectangle);
382 + set_dev_proc(*pbdev, copy_mono, gsijs_copy_mono);
383 + set_dev_proc(*pbdev, fill_mask, gsijs_fill_mask);
384 + set_dev_proc(*pbdev, fill_path, gsijs_fill_path);
385 + set_dev_proc(*pbdev, stroke_path, gsijs_stroke_path);
390 +/* See if IJS server supports krgb. */
392 +gsijs_set_krgb_mode(gx_device_ijs *ijsdev)
395 + int n_chan = ijsdev->color_info.num_components;
398 + ijsdev->krgb_mode = 0; /* default is no krgb */
401 + return 0; /* no krgb support, not RGB colorspace */
404 + code = ijs_client_enum_param(ijsdev->ctx, 0, "ColorSpace", buf, sizeof(buf)-1);
407 + if (strstr(buf, "KRGB") != NULL)
409 + ijsdev->krgb_mode = 1; /* yes KRGB is supported */
410 + ijsdev->k_bits = 1; /* KRGB = 1x8x8x8 */
412 + else if (strstr(buf, "KxRGB") != NULL)
414 + ijsdev->krgb_mode = 1; /* yes KRGB is supported */
415 + ijsdev->k_bits = 8; /* KRGB = 8x8x8x8 */
421 +/* ------ Private definitions ------ */
424 gsijs_parse_wxh (const char *val, int size, double *pw, double *ph)
429 - * gsijs_set_generic_params_hpijs: Set generic IJS parameters.
431 - * This version is specialized for hpijs 1.0 through 1.0.2, and
432 - * accommodates a number of quirks.
435 -gsijs_set_generic_params_hpijs(gx_device_ijs *ijsdev)
440 - /* IjsParams, Duplex, and Tumble get set at this point because
441 - they may affect margins. */
442 - if (ijsdev->IjsParams) {
443 - code = gsijs_client_set_param(ijsdev, "IjsParams", ijsdev->IjsParams);
446 - if (code == 0 && ijsdev->Duplex_set) {
449 - duplex_val = ijsdev->Duplex ? (ijsdev->IjsTumble ? 1 : 2) : 0;
450 - sprintf (buf, "%d", duplex_val);
451 - code = gsijs_client_set_param(ijsdev, "Duplex", buf);
457 * gsijs_set_generic_params: Set generic IJS parameters.
464 - if (ijsdev->ijs_version == HPIJS_1_0_VERSION)
465 - return gsijs_set_generic_params_hpijs(ijsdev);
467 /* Split IjsParams into separate parameters and send to ijs server */
469 for (i=0, j=0; (j < ijsdev->IjsParams_size) && (i < sizeof(buf)-1); j++) {
474 - * gsijs_set_margin_params_hpijs: Do margin negotiation with IJS server.
476 - * This version is specialized for hpijs 1.0 through 1.0.2, and
477 - * accommodates a number of quirks.
480 -gsijs_set_margin_params_hpijs(gx_device_ijs *ijsdev)
486 - sprintf(buf, "%d", ijsdev->width);
487 - code = gsijs_client_set_param(ijsdev, "Width", buf);
490 - sprintf(buf, "%d", ijsdev->height);
491 - code = gsijs_client_set_param(ijsdev, "Height", buf);
495 - double printable_width, printable_height;
496 - double printable_left, printable_top;
499 - code = ijs_client_get_param(ijsdev->ctx, 0, "PrintableArea",
501 - if (code == IJS_EUNKPARAM)
502 - /* IJS server doesn't support margin negotiations.
505 - else if (code >= 0) {
506 - code = gsijs_parse_wxh(buf, code,
507 - &printable_width, &printable_height);
511 - code = ijs_client_get_param(ijsdev->ctx, 0, "PrintableTopLeft",
513 - if (code == IJS_EUNKPARAM)
515 - else if (code >= 0) {
516 - code = gsijs_parse_wxh(buf, code,
517 - &printable_left, &printable_top);
522 - m[0] = printable_left;
523 - m[1] = ijsdev->MediaSize[1] * (1.0 / 72) -
524 - printable_top - printable_height;
525 - m[2] = ijsdev->MediaSize[0] * (1.0 / 72) -
526 - printable_left - printable_width;
527 - m[3] = printable_top;
528 - gx_device_set_margins((gx_device *)ijsdev, m, true);
536 * gsijs_set_margin_params: Do margin negotiation with IJS server.
543 - if (ijsdev->ijs_version == HPIJS_1_0_VERSION)
544 - return gsijs_set_margin_params_hpijs(ijsdev);
546 /* Split IjsParams into separate parameters and send to ijs server */
548 for (i=0, j=0; (j < ijsdev->IjsParams_size) && (i < sizeof(buf)-1); j++) {
550 return gs_note_error(gs_error_ioerror);
553 + ijsdev->space_params.banding_type = BandingAlways; /* always force banding */
555 + /* Set create_buf_device in printer device, so that we can hook the banding playback procedures. */
556 + ijsdev->printer_procs.buf_procs.create_buf_device = gsijs_create_buf_device;
558 /* Decide whether to use OutputFile or OutputFD. Note: how to
559 determine this is a tricky question, so we just allow the
563 code = gsijs_set_margin_params(ijsdev);
566 + code = gsijs_set_krgb_mode(ijsdev);
572 return min(width, end);
575 -static int ijs_all_white(unsigned char *data, int size)
579 - for (i = 0; i < size; i++)
581 - if (data[i] != 0xFF)
590 /* Print a page. Don't use normal printer gdev_prn_output_page
591 * because it opens the output file.
594 gx_device_printer *pdev = (gx_device_printer *)dev;
595 int raster = gdev_prn_raster(pdev);
596 int ijs_width, ijs_height;
598 + int row_bytes, k_row_bytes=0;
599 int n_chan = pdev->color_info.num_components;
600 + int krgb_mode = ijsdev->krgb_mode;
601 + int k_bits = ijsdev->k_bits;
604 double xres = pdev->HWResolution[0];
605 @@ -732,13 +995,23 @@
607 /* Determine bitmap width and height */
608 ijs_height = gdev_prn_print_scan_lines(dev);
609 - if (ijsdev->ijs_version == HPIJS_1_0_VERSION) {
610 - ijs_width = pdev->width;
612 ijs_width = gsijs_raster_width(dev);
615 row_bytes = (ijs_width * pdev->color_info.depth + 7) >> 3;
619 + gx_device_clist_common *cdev = (gx_device_clist_common *)dev;
620 + int band_height = cdev->page_info.band_params.BandHeight;
621 + k_row_bytes = (ijs_width + 7) >> 3;
623 + /* Create banding buffer for k plane. */
624 + ijsdev->k_width = ijs_width;
625 + ijsdev->k_band_size = band_height * k_row_bytes;
626 + if ((ijsdev->k_band = gs_malloc(pdev->memory, ijsdev->k_band_size, 1, "gsijs_output_page")) == (unsigned char *)NULL)
627 + return gs_note_error(gs_error_VMerror);
630 /* Required page parameters */
631 sprintf(buf, "%d", n_chan);
632 gsijs_client_set_param(ijsdev, "NumChan", buf);
633 @@ -747,44 +1020,71 @@
635 /* This needs to become more sophisticated for DeviceN. */
636 strcpy(buf, (n_chan == 4) ? "DeviceCMYK" :
637 - ((n_chan == 3) ? "DeviceRGB" : "DeviceGray"));
638 + ((n_chan == 3) ? (krgb_mode ? ((k_bits == 1) ? "KRGB" : "KxRGB") : "DeviceRGB") : "DeviceGray"));
639 gsijs_client_set_param(ijsdev, "ColorSpace", buf);
641 - /* If hpijs 1.0, don't set width and height here, because it
642 - expects them to be the paper size. */
643 - if (ijsdev->ijs_version != HPIJS_1_0_VERSION) {
644 - sprintf(buf, "%d", ijs_width);
645 - gsijs_client_set_param(ijsdev, "Width", buf);
646 - sprintf(buf, "%d", ijs_height);
647 - gsijs_client_set_param(ijsdev, "Height", buf);
649 + sprintf(buf, "%d", ijs_width);
650 + gsijs_client_set_param(ijsdev, "Width", buf);
651 + sprintf(buf, "%d", ijs_height);
652 + gsijs_client_set_param(ijsdev, "Height", buf);
654 sprintf(buf, "%gx%g", xres, yres);
655 gsijs_client_set_param(ijsdev, "Dpi", buf);
660 + kfd = open("/tmp/k.pbm", O_CREAT | O_TRUNC | O_RDWR, 0644);
661 + rgbfd = open("/tmp/rgb.ppm", O_CREAT | O_TRUNC | O_RDWR, 0644);
662 + snprintf(sz, sizeof(sz), "P4\n#gdevijs test\n%d\n%d\n", ijs_width, ijs_height);
663 + write(kfd, sz, strlen(sz));
664 + snprintf(sz, sizeof(sz), "P6\n#gdevijs test\n%d\n%d\n255\n", ijs_width, ijs_height);
665 + write(rgbfd, sz, strlen(sz));
668 for (i=0; i<num_copies; i++) {
669 unsigned char *actual_data;
670 ijs_client_begin_cmd (ijsdev->ctx, IJS_CMD_BEGIN_PAGE);
671 status = ijs_client_send_cmd_wait(ijsdev->ctx);
673 for (y = 0; y < ijs_height; y++) {
674 - code = gdev_prn_get_bits(pdev, y, data, &actual_data);
678 + code = gsijs_get_bits(pdev, y, data, &actual_data);
680 + code = gdev_prn_get_bits(pdev, y, data, &actual_data);
684 + write(rgbfd, actual_data, row_bytes);
686 + status = ijs_client_send_data_wait(ijsdev->ctx, 0, (char *)actual_data, row_bytes);
690 - if (ijsdev->ijs_version == HPIJS_1_0_VERSION &&
691 - ijs_all_white(actual_data, row_bytes))
692 - status = ijs_client_send_data_wait(ijsdev->ctx, 0, NULL, 0);
694 - status = ijs_client_send_data_wait(ijsdev->ctx, 0,
695 - (char *)actual_data, row_bytes);
699 + code = gsijs_k_get_bits(pdev, y, &actual_data);
703 + write(kfd, actual_data, k_row_bytes);
705 + status = ijs_client_send_data_wait(ijsdev->ctx, 0, (char *)actual_data, k_row_bytes);
710 ijs_client_begin_cmd(ijsdev->ctx, IJS_CMD_END_PAGE);
711 status = ijs_client_send_cmd_wait(ijsdev->ctx);
720 + gs_free(pdev->memory, ijsdev->k_band, ijsdev->k_band_size, 1, "gsijs_output_page");
722 gs_free_object(pdev->memory, data, "gsijs_output_page");
724 endcode = (pdev->buffer_space && !pdev->is_async_renderer ?
725 @@ -1090,7 +1390,6 @@
726 dprintf2("ijs: Can't set parameter %s=%s\n", key, value);
732 gsijs_set_color_format(gx_device_ijs *ijsdev)