xref: /plan9-contrib/sys/src/cmd/gs/src/gxclutil.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /* Copyright (C) 1998 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: gxclutil.c,v 1.12 2005/03/14 18:08:36 dan Exp $ */
187dd7cddfSDavid du Colombier /* Command list writing utilities. */
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier #include "memory_.h"
217dd7cddfSDavid du Colombier #include "string_.h"
227dd7cddfSDavid du Colombier #include "gx.h"
237dd7cddfSDavid du Colombier #include "gp.h"
247dd7cddfSDavid du Colombier #include "gpcheck.h"
257dd7cddfSDavid du Colombier #include "gserrors.h"
267dd7cddfSDavid du Colombier #include "gxdevice.h"
277dd7cddfSDavid du Colombier #include "gxdevmem.h"		/* must precede gxcldev.h */
287dd7cddfSDavid du Colombier #include "gxcldev.h"
297dd7cddfSDavid du Colombier #include "gxclpath.h"
307dd7cddfSDavid du Colombier #include "gsparams.h"
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier /* ---------------- Statistics ---------------- */
337dd7cddfSDavid du Colombier 
347dd7cddfSDavid du Colombier #ifdef DEBUG
357dd7cddfSDavid du Colombier const char *const cmd_op_names[16] =
367dd7cddfSDavid du Colombier {cmd_op_name_strings};
377dd7cddfSDavid du Colombier private const char *const cmd_misc_op_names[16] =
387dd7cddfSDavid du Colombier {cmd_misc_op_name_strings};
397dd7cddfSDavid du Colombier private const char *const cmd_misc2_op_names[16] =
407dd7cddfSDavid du Colombier {cmd_misc2_op_name_strings};
417dd7cddfSDavid du Colombier private const char *const cmd_segment_op_names[16] =
427dd7cddfSDavid du Colombier {cmd_segment_op_name_strings};
437dd7cddfSDavid du Colombier private const char *const cmd_path_op_names[16] =
447dd7cddfSDavid du Colombier {cmd_path_op_name_strings};
457dd7cddfSDavid du Colombier const char *const *const cmd_sub_op_names[16] =
467dd7cddfSDavid du Colombier {cmd_misc_op_names, 0, 0, 0, 0, 0, 0, 0,
477dd7cddfSDavid du Colombier  0, 0, 0, 0,
487dd7cddfSDavid du Colombier  0, cmd_misc2_op_names, cmd_segment_op_names, cmd_path_op_names
497dd7cddfSDavid du Colombier };
507dd7cddfSDavid du Colombier struct stats_cmd_s {
517dd7cddfSDavid du Colombier     ulong op_counts[256];
527dd7cddfSDavid du Colombier     ulong op_sizes[256];
537dd7cddfSDavid du Colombier     ulong tile_reset, tile_found, tile_added;
547dd7cddfSDavid du Colombier     ulong same_band, other_band;
557dd7cddfSDavid du Colombier } stats_cmd;
567dd7cddfSDavid du Colombier extern ulong stats_cmd_diffs[5];	/* in gxclpath.c */
577dd7cddfSDavid du Colombier int
cmd_count_op(int op,uint size)587dd7cddfSDavid du Colombier cmd_count_op(int op, uint size)
597dd7cddfSDavid du Colombier {
607dd7cddfSDavid du Colombier     stats_cmd.op_counts[op]++;
617dd7cddfSDavid du Colombier     stats_cmd.op_sizes[op] += size;
627dd7cddfSDavid du Colombier     if (gs_debug_c('L')) {
637dd7cddfSDavid du Colombier 	const char *const *sub = cmd_sub_op_names[op >> 4];
647dd7cddfSDavid du Colombier 
657dd7cddfSDavid du Colombier 	if (sub)
667dd7cddfSDavid du Colombier 	    dlprintf2(", %s(%u)\n", sub[op & 0xf], size);
677dd7cddfSDavid du Colombier 	else
687dd7cddfSDavid du Colombier 	    dlprintf3(", %s %d(%u)\n", cmd_op_names[op >> 4], op & 0xf,
697dd7cddfSDavid du Colombier 		      size);
703ff48bf5SDavid du Colombier 	dflush();
717dd7cddfSDavid du Colombier     }
727dd7cddfSDavid du Colombier     return op;
737dd7cddfSDavid du Colombier }
747dd7cddfSDavid du Colombier void
cmd_uncount_op(int op,uint size)757dd7cddfSDavid du Colombier cmd_uncount_op(int op, uint size)
767dd7cddfSDavid du Colombier {
777dd7cddfSDavid du Colombier     stats_cmd.op_counts[op]--;
787dd7cddfSDavid du Colombier     stats_cmd.op_sizes[op] -= size;
797dd7cddfSDavid du Colombier }
807dd7cddfSDavid du Colombier #endif
817dd7cddfSDavid du Colombier 
827dd7cddfSDavid du Colombier /* Print statistics. */
837dd7cddfSDavid du Colombier #ifdef DEBUG
847dd7cddfSDavid du Colombier void
cmd_print_stats(void)857dd7cddfSDavid du Colombier cmd_print_stats(void)
867dd7cddfSDavid du Colombier {
877dd7cddfSDavid du Colombier     int ci, cj;
887dd7cddfSDavid du Colombier 
897dd7cddfSDavid du Colombier     dlprintf3("[l]counts: reset = %lu, found = %lu, added = %lu\n",
907dd7cddfSDavid du Colombier 	      stats_cmd.tile_reset, stats_cmd.tile_found,
917dd7cddfSDavid du Colombier 	      stats_cmd.tile_added);
927dd7cddfSDavid du Colombier     dlprintf5("     diff 2.5 = %lu, 3 = %lu, 4 = %lu, 2 = %lu, >4 = %lu\n",
937dd7cddfSDavid du Colombier 	      stats_cmd_diffs[0], stats_cmd_diffs[1], stats_cmd_diffs[2],
947dd7cddfSDavid du Colombier 	      stats_cmd_diffs[3], stats_cmd_diffs[4]);
957dd7cddfSDavid du Colombier     dlprintf2("     same_band = %lu, other_band = %lu\n",
967dd7cddfSDavid du Colombier 	      stats_cmd.same_band, stats_cmd.other_band);
977dd7cddfSDavid du Colombier     for (ci = 0; ci < 0x100; ci += 0x10) {
987dd7cddfSDavid du Colombier 	const char *const *sub = cmd_sub_op_names[ci >> 4];
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier 	if (sub != 0) {
1017dd7cddfSDavid du Colombier 	    dlprintf1("[l]  %s =", cmd_op_names[ci >> 4]);
1027dd7cddfSDavid du Colombier 	    for (cj = ci; cj < ci + 0x10; cj += 2)
1037dd7cddfSDavid du Colombier 		dprintf6("\n\t%s = %lu(%lu), %s = %lu(%lu)",
1047dd7cddfSDavid du Colombier 			 sub[cj - ci],
1057dd7cddfSDavid du Colombier 			 stats_cmd.op_counts[cj], stats_cmd.op_sizes[cj],
1067dd7cddfSDavid du Colombier 			 sub[cj - ci + 1],
1077dd7cddfSDavid du Colombier 		   stats_cmd.op_counts[cj + 1], stats_cmd.op_sizes[cj + 1]);
1087dd7cddfSDavid du Colombier 	} else {
1097dd7cddfSDavid du Colombier 	    ulong tcounts = 0, tsizes = 0;
1107dd7cddfSDavid du Colombier 
1117dd7cddfSDavid du Colombier 	    for (cj = ci; cj < ci + 0x10; cj++)
1127dd7cddfSDavid du Colombier 		tcounts += stats_cmd.op_counts[cj],
1137dd7cddfSDavid du Colombier 		    tsizes += stats_cmd.op_sizes[cj];
1147dd7cddfSDavid du Colombier 	    dlprintf3("[l]  %s (%lu,%lu) =\n\t",
1157dd7cddfSDavid du Colombier 		      cmd_op_names[ci >> 4], tcounts, tsizes);
1167dd7cddfSDavid du Colombier 	    for (cj = ci; cj < ci + 0x10; cj++)
1177dd7cddfSDavid du Colombier 		if (stats_cmd.op_counts[cj] == 0)
1187dd7cddfSDavid du Colombier 		    dputs(" -");
1197dd7cddfSDavid du Colombier 		else
1207dd7cddfSDavid du Colombier 		    dprintf2(" %lu(%lu)", stats_cmd.op_counts[cj],
1217dd7cddfSDavid du Colombier 			     stats_cmd.op_sizes[cj]);
1227dd7cddfSDavid du Colombier 	}
1237dd7cddfSDavid du Colombier 	dputs("\n");
1247dd7cddfSDavid du Colombier     }
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier #endif /* DEBUG */
1277dd7cddfSDavid du Colombier 
1287dd7cddfSDavid du Colombier /* ---------------- Writing utilities ---------------- */
1297dd7cddfSDavid du Colombier 
1307dd7cddfSDavid du Colombier /* Write the commands for one band or band range. */
1317dd7cddfSDavid du Colombier private int	/* ret 0 all ok, -ve error code, or +1 ok w/low-mem warning */
cmd_write_band(gx_device_clist_writer * cldev,int band_min,int band_max,cmd_list * pcl,byte cmd_end)1327dd7cddfSDavid du Colombier cmd_write_band(gx_device_clist_writer * cldev, int band_min, int band_max,
1337dd7cddfSDavid du Colombier 	       cmd_list * pcl, byte cmd_end)
1347dd7cddfSDavid du Colombier {
1357dd7cddfSDavid du Colombier     const cmd_prefix *cp = pcl->head;
1367dd7cddfSDavid du Colombier     int code_b = 0;
1377dd7cddfSDavid du Colombier     int code_c = 0;
1387dd7cddfSDavid du Colombier 
1397dd7cddfSDavid du Colombier     if (cp != 0 || cmd_end != cmd_opv_end_run) {
1407dd7cddfSDavid du Colombier 	clist_file_ptr cfile = cldev->page_cfile;
1417dd7cddfSDavid du Colombier 	clist_file_ptr bfile = cldev->page_bfile;
1427dd7cddfSDavid du Colombier 	cmd_block cb;
1437dd7cddfSDavid du Colombier 	byte end = cmd_count_op(cmd_end, 1);
1447dd7cddfSDavid du Colombier 
1457dd7cddfSDavid du Colombier 	if (cfile == 0 || bfile == 0)
1467dd7cddfSDavid du Colombier  	    return_error(gs_error_ioerror);
1477dd7cddfSDavid du Colombier 	cb.band_min = band_min;
1487dd7cddfSDavid du Colombier 	cb.band_max = band_max;
1497dd7cddfSDavid du Colombier 	cb.pos = clist_ftell(cfile);
1507dd7cddfSDavid du Colombier 	if_debug3('l', "[l]writing for bands (%d,%d) at %ld\n",
1517dd7cddfSDavid du Colombier 		  band_min, band_max, cb.pos);
1527dd7cddfSDavid du Colombier 	clist_fwrite_chars(&cb, sizeof(cb), bfile);
1537dd7cddfSDavid du Colombier 	if (cp != 0) {
1547dd7cddfSDavid du Colombier 	    pcl->tail->next = 0;	/* terminate the list */
1557dd7cddfSDavid du Colombier 	    for (; cp != 0; cp = cp->next) {
1567dd7cddfSDavid du Colombier #ifdef DEBUG
1577dd7cddfSDavid du Colombier 		if ((const byte *)cp < cldev->cbuf ||
1587dd7cddfSDavid du Colombier 		    (const byte *)cp >= cldev->cend ||
1597dd7cddfSDavid du Colombier 		    cp->size > cldev->cend - (const byte *)cp
1607dd7cddfSDavid du Colombier 		    ) {
1617dd7cddfSDavid du Colombier 		    lprintf1("cmd_write_band error at 0x%lx\n", (ulong) cp);
1627dd7cddfSDavid du Colombier 		    return_error(gs_error_Fatal);
1637dd7cddfSDavid du Colombier 		}
1647dd7cddfSDavid du Colombier #endif
1657dd7cddfSDavid du Colombier 		clist_fwrite_chars(cp + 1, cp->size, cfile);
1667dd7cddfSDavid du Colombier 	    }
1677dd7cddfSDavid du Colombier 	    pcl->head = pcl->tail = 0;
1687dd7cddfSDavid du Colombier 	}
1697dd7cddfSDavid du Colombier 	clist_fwrite_chars(&end, 1, cfile);
170*593dc095SDavid du Colombier 	process_interrupts(cldev->memory);
1717dd7cddfSDavid du Colombier 	code_b = clist_ferror_code(bfile);
1727dd7cddfSDavid du Colombier 	code_c = clist_ferror_code(cfile);
1737dd7cddfSDavid du Colombier 	if (code_b < 0)
1747dd7cddfSDavid du Colombier 	    return_error(code_b);
1757dd7cddfSDavid du Colombier 	if (code_c < 0)
1767dd7cddfSDavid du Colombier 	    return_error(code_c);
1777dd7cddfSDavid du Colombier     }
1787dd7cddfSDavid du Colombier     return code_b | code_c;
1797dd7cddfSDavid du Colombier }
1807dd7cddfSDavid du Colombier 
1817dd7cddfSDavid du Colombier /* Write out the buffered commands, and reset the buffer. */
1827dd7cddfSDavid du Colombier int	/* ret 0 all-ok, -ve error code, or +1 ok w/low-mem warning */
cmd_write_buffer(gx_device_clist_writer * cldev,byte cmd_end)1837dd7cddfSDavid du Colombier cmd_write_buffer(gx_device_clist_writer * cldev, byte cmd_end)
1847dd7cddfSDavid du Colombier {
1857dd7cddfSDavid du Colombier     int nbands = cldev->nbands;
1867dd7cddfSDavid du Colombier     gx_clist_state *pcls;
1877dd7cddfSDavid du Colombier     int band;
1887dd7cddfSDavid du Colombier     int code = cmd_write_band(cldev, cldev->band_range_min,
1897dd7cddfSDavid du Colombier 			      cldev->band_range_max,
1907dd7cddfSDavid du Colombier 			      &cldev->band_range_list, cmd_opv_end_run);
1917dd7cddfSDavid du Colombier     int warning = code;
1927dd7cddfSDavid du Colombier 
1937dd7cddfSDavid du Colombier     for (band = 0, pcls = cldev->states;
1947dd7cddfSDavid du Colombier 	 code >= 0 && band < nbands; band++, pcls++
1957dd7cddfSDavid du Colombier 	 ) {
1967dd7cddfSDavid du Colombier 	code = cmd_write_band(cldev, band, band, &pcls->list, cmd_end);
1977dd7cddfSDavid du Colombier 	warning |= code;
1987dd7cddfSDavid du Colombier     }
1997dd7cddfSDavid du Colombier     /* If an error occurred, finish cleaning up the pointers. */
2007dd7cddfSDavid du Colombier     for (; band < nbands; band++, pcls++)
2017dd7cddfSDavid du Colombier 	pcls->list.head = pcls->list.tail = 0;
2027dd7cddfSDavid du Colombier     cldev->cnext = cldev->cbuf;
2037dd7cddfSDavid du Colombier     cldev->ccl = 0;
2047dd7cddfSDavid du Colombier #ifdef DEBUG
2057dd7cddfSDavid du Colombier     if (gs_debug_c('l'))
2067dd7cddfSDavid du Colombier 	cmd_print_stats();
2077dd7cddfSDavid du Colombier #endif
208*593dc095SDavid du Colombier     return_check_interrupt(cldev->memory, code != 0 ? code : warning);
2097dd7cddfSDavid du Colombier }
2107dd7cddfSDavid du Colombier 
2117dd7cddfSDavid du Colombier /*
2127dd7cddfSDavid du Colombier  * Add a command to the appropriate band list, and allocate space for its
2137dd7cddfSDavid du Colombier  * data.  Return the pointer to the data area.  If an error or (low-memory
2147dd7cddfSDavid du Colombier  * warning) occurs, set cldev->error_code and return 0.
2157dd7cddfSDavid du Colombier  */
2167dd7cddfSDavid du Colombier #define cmd_headroom (sizeof(cmd_prefix) + arch_align_ptr_mod)
2177dd7cddfSDavid du Colombier byte *
cmd_put_list_op(gx_device_clist_writer * cldev,cmd_list * pcl,uint size)2187dd7cddfSDavid du Colombier cmd_put_list_op(gx_device_clist_writer * cldev, cmd_list * pcl, uint size)
2197dd7cddfSDavid du Colombier {
2207dd7cddfSDavid du Colombier     byte *dp = cldev->cnext;
2217dd7cddfSDavid du Colombier 
2227dd7cddfSDavid du Colombier     if (size + cmd_headroom > cldev->cend - dp) {
2237dd7cddfSDavid du Colombier 	if ((cldev->error_code =
2247dd7cddfSDavid du Colombier 	       cmd_write_buffer(cldev, cmd_opv_end_run)) != 0) {
2257dd7cddfSDavid du Colombier 	    if (cldev->error_code < 0)
2267dd7cddfSDavid du Colombier 		cldev->error_is_retryable = 0;	/* hard error */
2277dd7cddfSDavid du Colombier 	    else {
2287dd7cddfSDavid du Colombier 		/* upgrade lo-mem warning into an error */
2297dd7cddfSDavid du Colombier 		if (!cldev->ignore_lo_mem_warnings)
2307dd7cddfSDavid du Colombier 		    cldev->error_code = gs_note_error(gs_error_VMerror);
2317dd7cddfSDavid du Colombier 		cldev->error_is_retryable = 1;
2327dd7cddfSDavid du Colombier 	    }
2337dd7cddfSDavid du Colombier 	    return 0;
2347dd7cddfSDavid du Colombier 	}
2357dd7cddfSDavid du Colombier 	else
2367dd7cddfSDavid du Colombier 	    return cmd_put_list_op(cldev, pcl, size);
2377dd7cddfSDavid du Colombier     }
2387dd7cddfSDavid du Colombier     if (cldev->ccl == pcl) {	/* We're adding another command for the same band. */
2397dd7cddfSDavid du Colombier 	/* Tack it onto the end of the previous one. */
2407dd7cddfSDavid du Colombier 	cmd_count_add1(stats_cmd.same_band);
2417dd7cddfSDavid du Colombier #ifdef DEBUG
2427dd7cddfSDavid du Colombier 	if (pcl->tail->size > dp - (byte *) (pcl->tail + 1)) {
2437dd7cddfSDavid du Colombier 	    lprintf1("cmd_put_list_op error at 0x%lx\n", (ulong) pcl->tail);
2447dd7cddfSDavid du Colombier 	}
2457dd7cddfSDavid du Colombier #endif
2467dd7cddfSDavid du Colombier 	pcl->tail->size += size;
2477dd7cddfSDavid du Colombier     } else {
2487dd7cddfSDavid du Colombier 	/* Skip to an appropriate alignment boundary. */
2497dd7cddfSDavid du Colombier 	/* (We assume the command buffer itself is aligned.) */
2507dd7cddfSDavid du Colombier 	cmd_prefix *cp = (cmd_prefix *)
2517dd7cddfSDavid du Colombier 	    (dp + ((cldev->cbuf - dp) & (arch_align_ptr_mod - 1)));
2527dd7cddfSDavid du Colombier 
2537dd7cddfSDavid du Colombier 	cmd_count_add1(stats_cmd.other_band);
2547dd7cddfSDavid du Colombier 	dp = (byte *) (cp + 1);
2557dd7cddfSDavid du Colombier 	if (pcl->tail != 0) {
2567dd7cddfSDavid du Colombier #ifdef DEBUG
2577dd7cddfSDavid du Colombier 	    if (pcl->tail < pcl->head ||
2587dd7cddfSDavid du Colombier 		pcl->tail->size > dp - (byte *) (pcl->tail + 1)
2597dd7cddfSDavid du Colombier 		) {
2607dd7cddfSDavid du Colombier 		lprintf1("cmd_put_list_op error at 0x%lx\n",
2617dd7cddfSDavid du Colombier 			 (ulong) pcl->tail);
2627dd7cddfSDavid du Colombier 	    }
2637dd7cddfSDavid du Colombier #endif
2647dd7cddfSDavid du Colombier 	    pcl->tail->next = cp;
2657dd7cddfSDavid du Colombier 	} else
2667dd7cddfSDavid du Colombier 	    pcl->head = cp;
2677dd7cddfSDavid du Colombier 	pcl->tail = cp;
2687dd7cddfSDavid du Colombier 	cldev->ccl = pcl;
2697dd7cddfSDavid du Colombier 	cp->size = size;
2707dd7cddfSDavid du Colombier     }
2717dd7cddfSDavid du Colombier     cldev->cnext = dp + size;
2727dd7cddfSDavid du Colombier     return dp;
2737dd7cddfSDavid du Colombier }
2747dd7cddfSDavid du Colombier #ifdef DEBUG
2757dd7cddfSDavid du Colombier byte *
cmd_put_op(gx_device_clist_writer * cldev,gx_clist_state * pcls,uint size)2767dd7cddfSDavid du Colombier cmd_put_op(gx_device_clist_writer * cldev, gx_clist_state * pcls, uint size)
2777dd7cddfSDavid du Colombier {
2787dd7cddfSDavid du Colombier     if_debug3('L', "[L]band %d: size=%u, left=%u",
2797dd7cddfSDavid du Colombier 	      (int)(pcls - cldev->states),
280*593dc095SDavid du Colombier 	      size, 0);
2817dd7cddfSDavid du Colombier     return cmd_put_list_op(cldev, &pcls->list, size);
2827dd7cddfSDavid du Colombier }
2837dd7cddfSDavid du Colombier #endif
2847dd7cddfSDavid du Colombier 
2857dd7cddfSDavid du Colombier /* Add a command for a range of bands. */
2867dd7cddfSDavid du Colombier byte *
cmd_put_range_op(gx_device_clist_writer * cldev,int band_min,int band_max,uint size)2877dd7cddfSDavid du Colombier cmd_put_range_op(gx_device_clist_writer * cldev, int band_min, int band_max,
2887dd7cddfSDavid du Colombier 		 uint size)
2897dd7cddfSDavid du Colombier {
2907dd7cddfSDavid du Colombier     if_debug4('L', "[L]band range(%d,%d): size=%u, left=%u",
291*593dc095SDavid du Colombier 	      band_min, band_max, size, 0);
2927dd7cddfSDavid du Colombier     if (cldev->ccl != 0 &&
2937dd7cddfSDavid du Colombier 	(cldev->ccl != &cldev->band_range_list ||
2947dd7cddfSDavid du Colombier 	 band_min != cldev->band_range_min ||
2957dd7cddfSDavid du Colombier 	 band_max != cldev->band_range_max)
2967dd7cddfSDavid du Colombier 	) {
2977dd7cddfSDavid du Colombier 	if ((cldev->error_code = cmd_write_buffer(cldev, cmd_opv_end_run)) != 0) {
2987dd7cddfSDavid du Colombier 	    if (cldev->error_code < 0)
2997dd7cddfSDavid du Colombier 		cldev->error_is_retryable = 0;	/* hard error */
3007dd7cddfSDavid du Colombier 	    else {
3017dd7cddfSDavid du Colombier 		/* upgrade lo-mem warning into an error */
3027dd7cddfSDavid du Colombier 		cldev->error_code = gs_error_VMerror;
3037dd7cddfSDavid du Colombier 		cldev->error_is_retryable = 1;
3047dd7cddfSDavid du Colombier 	    }
3057dd7cddfSDavid du Colombier 	    return 0;
3067dd7cddfSDavid du Colombier 	}
3077dd7cddfSDavid du Colombier 	cldev->band_range_min = band_min;
3087dd7cddfSDavid du Colombier 	cldev->band_range_max = band_max;
3097dd7cddfSDavid du Colombier     }
3107dd7cddfSDavid du Colombier     return cmd_put_list_op(cldev, &cldev->band_range_list, size);
3117dd7cddfSDavid du Colombier }
3127dd7cddfSDavid du Colombier 
3137dd7cddfSDavid du Colombier /* Write a variable-size positive integer. */
3147dd7cddfSDavid du Colombier int
cmd_size_w(register uint w)3157dd7cddfSDavid du Colombier cmd_size_w(register uint w)
3167dd7cddfSDavid du Colombier {
3177dd7cddfSDavid du Colombier     register int size = 1;
3187dd7cddfSDavid du Colombier 
3197dd7cddfSDavid du Colombier     while (w > 0x7f)
3207dd7cddfSDavid du Colombier 	w >>= 7, size++;
3217dd7cddfSDavid du Colombier     return size;
3227dd7cddfSDavid du Colombier }
3237dd7cddfSDavid du Colombier byte *
cmd_put_w(register uint w,register byte * dp)3247dd7cddfSDavid du Colombier cmd_put_w(register uint w, register byte * dp)
3257dd7cddfSDavid du Colombier {
3267dd7cddfSDavid du Colombier     while (w > 0x7f)
3277dd7cddfSDavid du Colombier 	*dp++ = w | 0x80, w >>= 7;
3287dd7cddfSDavid du Colombier     *dp = w;
3297dd7cddfSDavid du Colombier     return dp + 1;
3307dd7cddfSDavid du Colombier }
3317dd7cddfSDavid du Colombier 
332*593dc095SDavid du Colombier 
333*593dc095SDavid du Colombier /*
334*593dc095SDavid du Colombier  * This next two arrays are used for the 'delta' mode of placing a color
335*593dc095SDavid du Colombier  * in the clist.  These arrays are indexed by the number of bytes in the
336*593dc095SDavid du Colombier  * color value (the depth).
337*593dc095SDavid du Colombier  *
338*593dc095SDavid du Colombier  * Delta values are calculated by subtracting the old value for the color
339*593dc095SDavid du Colombier  * from the desired new value.  Then each byte of the differenece is
340*593dc095SDavid du Colombier  * examined.  For most bytes, if the difference fits into 4 bits (signed)
341*593dc095SDavid du Colombier  * then those bits are packed into the clist along with an opcode.  If
342*593dc095SDavid du Colombier  * the size of the color (the depth) is an odd number of bytes then instead
343*593dc095SDavid du Colombier  * of four bits per byte, extra bits are used for the upper three bytes
344*593dc095SDavid du Colombier  * of the color.  In this case, five bits are used for the first byte,
345*593dc095SDavid du Colombier  * six bits for the second byte, and five bits for third byte.  This
346*593dc095SDavid du Colombier  * maximizes the chance that the 'delta' mode can be used for placing
347*593dc095SDavid du Colombier  * colors in the clist.
348*593dc095SDavid du Colombier  */
349*593dc095SDavid du Colombier /*
350*593dc095SDavid du Colombier  * Depending upon the compiler and user choices, the size of a gx_color_index
351*593dc095SDavid du Colombier  * may be 4 to 8 bytes.  We will define table entries for up to 8 bytes.
352*593dc095SDavid du Colombier  * This macro is being used to prevent compiler warnings if gx_color_index is
353*593dc095SDavid du Colombier  * only 4 bytes.
354*593dc095SDavid du Colombier  */
355*593dc095SDavid du Colombier #define tab_entry(x) ((x) & (~((gx_color_index) 0)))
356*593dc095SDavid du Colombier 
357*593dc095SDavid du Colombier const gx_color_index cmd_delta_offsets[] = {
358*593dc095SDavid du Colombier 	tab_entry(0),
359*593dc095SDavid du Colombier 	tab_entry(0),
360*593dc095SDavid du Colombier 	tab_entry(0x0808),
361*593dc095SDavid du Colombier 	tab_entry(0x102010),
362*593dc095SDavid du Colombier 	tab_entry(0x08080808),
363*593dc095SDavid du Colombier 	tab_entry(0x1020100808),
364*593dc095SDavid du Colombier 	tab_entry(0x080808080808),
365*593dc095SDavid du Colombier 	tab_entry(0x10201008080808),
366*593dc095SDavid du Colombier 	tab_entry(0x0808080808080808),
367*593dc095SDavid du Colombier 	};
368*593dc095SDavid du Colombier 
369*593dc095SDavid du Colombier private const gx_color_index cmd_delta_masks[] = {
370*593dc095SDavid du Colombier 	tab_entry(0),
371*593dc095SDavid du Colombier 	tab_entry(0),
372*593dc095SDavid du Colombier 	tab_entry(0x0f0f),
373*593dc095SDavid du Colombier 	tab_entry(0x1f3f1f),
374*593dc095SDavid du Colombier 	tab_entry(0x0f0f0f0f),
375*593dc095SDavid du Colombier 	tab_entry(0x1f3f1f0f0f),
376*593dc095SDavid du Colombier 	tab_entry(0x0f0f0f0f0f0f),
377*593dc095SDavid du Colombier 	tab_entry(0x1f3f1f0f0f0f0f),
378*593dc095SDavid du Colombier 	tab_entry(0x0f0f0f0f0f0f0f0f),
379*593dc095SDavid du Colombier 	};
380*593dc095SDavid du Colombier 
381*593dc095SDavid du Colombier #undef tab_entry
382*593dc095SDavid du Colombier 
383*593dc095SDavid du Colombier /*
384*593dc095SDavid du Colombier  * There are currently only four different color "types" that can be placed
385*593dc095SDavid du Colombier  * into the clist.  These are called "color0", "color1", and "tile_color0",
386*593dc095SDavid du Colombier  * and "tile_color1".  There are separate command codes for color0 versus
387*593dc095SDavid du Colombier  * color1, both for the full value and delta commands - see cmd_put_color.
388*593dc095SDavid du Colombier  * Tile colors are preceded by a cmd_opv_set_tile_color command.
389*593dc095SDavid du Colombier  */
3907dd7cddfSDavid du Colombier const clist_select_color_t
391*593dc095SDavid du Colombier     clist_select_color0 = {cmd_op_set_color0, cmd_opv_delta_color0, 0},
392*593dc095SDavid du Colombier     clist_select_color1 = {cmd_op_set_color1, cmd_opv_delta_color1, 0},
393*593dc095SDavid du Colombier     clist_select_tile_color0 = {cmd_op_set_color0, cmd_opv_delta_color0, 1},
394*593dc095SDavid du Colombier     clist_select_tile_color1 = {cmd_op_set_color1, cmd_opv_delta_color1, 1};
395*593dc095SDavid du Colombier 
396*593dc095SDavid du Colombier /*
397*593dc095SDavid du Colombier  * This routine is used to place a color into the clist.  Colors, in the
398*593dc095SDavid du Colombier  * clist, can be specified either as by a full value or by a "delta" value.
399*593dc095SDavid du Colombier  *
400*593dc095SDavid du Colombier  * See the comments before cmd_delta_offsets[] for a description of the
401*593dc095SDavid du Colombier  * 'delta' mode.  The delta mode may allow for a smaller command in the clist.
402*593dc095SDavid du Colombier  *
403*593dc095SDavid du Colombier  * For the full value mode, values are sent as a cmd code plus n bytes of
404*593dc095SDavid du Colombier  * data.  To minimize the number of bytes, a count is made of any low order
405*593dc095SDavid du Colombier  * bytes which are zero.  This count is packed into the low order 4 bits
406*593dc095SDavid du Colombier  * of the cmd code.  The data for these bytes are not sent.
407*593dc095SDavid du Colombier  *
408*593dc095SDavid du Colombier  * The gx_no_color_index value is treated as a special case.  This is done
409*593dc095SDavid du Colombier  * because it is both a commonly sent value and because it may require
410*593dc095SDavid du Colombier  * more bytes then the other color values.
411*593dc095SDavid du Colombier  *
412*593dc095SDavid du Colombier  * Parameters:
413*593dc095SDavid du Colombier  *   cldev - Pointer to clist device
414*593dc095SDavid du Colombier  *   pcls - Pointer to clist state
415*593dc095SDavid du Colombier  *   select - Descriptor record for type of color being sent.  See comments
416*593dc095SDavid du Colombier  *       by clist_select_color_t.
417*593dc095SDavid du Colombier  *   color - The new color value.
418*593dc095SDavid du Colombier  *   pcolor - Pointer to previous color value.  (If the color value is the
419*593dc095SDavid du Colombier  *       same as the previous value then nothing is placed into the clist.)
420*593dc095SDavid du Colombier  *
421*593dc095SDavid du Colombier  * Returns:
422*593dc095SDavid du Colombier  *   Error code
423*593dc095SDavid du Colombier  *   clist and pcls and cldev may be updated.
424*593dc095SDavid du Colombier  */
4257dd7cddfSDavid du Colombier int
cmd_put_color(gx_device_clist_writer * cldev,gx_clist_state * pcls,const clist_select_color_t * select,gx_color_index color,gx_color_index * pcolor)4267dd7cddfSDavid du Colombier cmd_put_color(gx_device_clist_writer * cldev, gx_clist_state * pcls,
4277dd7cddfSDavid du Colombier 	      const clist_select_color_t * select,
4287dd7cddfSDavid du Colombier 	      gx_color_index color, gx_color_index * pcolor)
4297dd7cddfSDavid du Colombier {
430*593dc095SDavid du Colombier     byte * dp;		/* This is manipulated by the set_cmd_put_op macro */
431*593dc095SDavid du Colombier     gx_color_index diff = color - *pcolor;
432*593dc095SDavid du Colombier     byte op, op_delta;
4337dd7cddfSDavid du Colombier     int code;
4347dd7cddfSDavid du Colombier 
4357dd7cddfSDavid du Colombier     if (diff == 0)
4367dd7cddfSDavid du Colombier 	return 0;
437*593dc095SDavid du Colombier 
438*593dc095SDavid du Colombier     /* If this is a tile color then send tile color type */
4397dd7cddfSDavid du Colombier     if (select->tile_color) {
4407dd7cddfSDavid du Colombier 	code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_tile_color, 1);
4417dd7cddfSDavid du Colombier 	if (code < 0)
4427dd7cddfSDavid du Colombier 	    return code;
4437dd7cddfSDavid du Colombier     }
4447dd7cddfSDavid du Colombier     op = select->set_op;
445*593dc095SDavid du Colombier     op_delta = select->delta_op;
4467dd7cddfSDavid du Colombier     if (color == gx_no_color_index) {
4477dd7cddfSDavid du Colombier 	/*
4487dd7cddfSDavid du Colombier 	 * We must handle this specially, because it may take more
4497dd7cddfSDavid du Colombier 	 * bytes than the color depth.
4507dd7cddfSDavid du Colombier 	 */
451*593dc095SDavid du Colombier 	code = set_cmd_put_op(dp, cldev, pcls, op + cmd_no_color_index, 1);
4527dd7cddfSDavid du Colombier 	if (code < 0)
4537dd7cddfSDavid du Colombier 	    return code;
4547dd7cddfSDavid du Colombier     } else {
455*593dc095SDavid du Colombier 	/* Check if the "delta" mode command can be used. */
456*593dc095SDavid du Colombier 	int num_bytes = (cldev->color_info.depth + 7) >> 3;
457*593dc095SDavid du Colombier 	int delta_bytes = (num_bytes + 1) / 2;
458*593dc095SDavid du Colombier 	gx_color_index delta_offset = cmd_delta_offsets[num_bytes];
459*593dc095SDavid du Colombier 	gx_color_index delta_mask = cmd_delta_masks[num_bytes];
460*593dc095SDavid du Colombier 	gx_color_index delta = (diff + delta_offset) & delta_mask;
461*593dc095SDavid du Colombier 	bool use_delta = (color == (*pcolor + delta - delta_offset));
462*593dc095SDavid du Colombier 	int bytes_dropped = 0;
463*593dc095SDavid du Colombier 	gx_color_index data = color;
4647dd7cddfSDavid du Colombier 
465*593dc095SDavid du Colombier 	/*
466*593dc095SDavid du Colombier 	 * If we use the full value mode, we do not send low order bytes
467*593dc095SDavid du Colombier 	 * which are zero. Determine how many low order bytes are zero.
468*593dc095SDavid du Colombier 	 */
469*593dc095SDavid du Colombier 	if (color == 0) {
470*593dc095SDavid du Colombier 	    bytes_dropped = num_bytes;
471*593dc095SDavid du Colombier 	}
472*593dc095SDavid du Colombier 	else  {
473*593dc095SDavid du Colombier 	    while ((data & 0xff) == 0) {
474*593dc095SDavid du Colombier 	        bytes_dropped++;
475*593dc095SDavid du Colombier 		data >>= 8;
476*593dc095SDavid du Colombier 	    }
477*593dc095SDavid du Colombier 	}
478*593dc095SDavid du Colombier 
479*593dc095SDavid du Colombier 	/* Now send one of the two command forms */
480*593dc095SDavid du Colombier 	if (use_delta && delta_bytes < num_bytes - bytes_dropped) {
4817dd7cddfSDavid du Colombier 	    code = set_cmd_put_op(dp, cldev, pcls,
482*593dc095SDavid du Colombier 	    				op_delta, delta_bytes + 1);
4837dd7cddfSDavid du Colombier 	    if (code < 0)
4847dd7cddfSDavid du Colombier 	        return code;
485*593dc095SDavid du Colombier 	    /*
486*593dc095SDavid du Colombier 	     * If we have an odd number of bytes then use extra bits for
487*593dc095SDavid du Colombier 	     * the high order three bytes of the color.
488*593dc095SDavid du Colombier 	     */
489*593dc095SDavid du Colombier 	    if ((num_bytes >= 3) && (num_bytes & 1)) {
490*593dc095SDavid du Colombier 		data = delta >> ((num_bytes - 3) * 8);
491*593dc095SDavid du Colombier 	        dp[delta_bytes--] = (byte)(((data >> 13) & 0xf8) + ((data >> 11) & 0x07));
492*593dc095SDavid du Colombier 	        dp[delta_bytes--] = (byte)(((data >> 3) & 0xe0) + (data & 0x1f));
4937dd7cddfSDavid du Colombier 	    }
494*593dc095SDavid du Colombier 	    for(; delta_bytes>0; delta_bytes--) {
495*593dc095SDavid du Colombier 	        dp[delta_bytes] = (byte)((delta >> 4) + delta);
496*593dc095SDavid du Colombier 		delta >>= 16;
4977dd7cddfSDavid du Colombier 	    }
498*593dc095SDavid du Colombier 	}
499*593dc095SDavid du Colombier 	else {
500*593dc095SDavid du Colombier 	    num_bytes -= bytes_dropped;
5017dd7cddfSDavid du Colombier 	    code = set_cmd_put_op(dp, cldev, pcls,
502*593dc095SDavid du Colombier 	    			(byte)(op + bytes_dropped), num_bytes + 1);
5037dd7cddfSDavid du Colombier 	    if (code < 0)
5047dd7cddfSDavid du Colombier 	        return code;
505*593dc095SDavid du Colombier 	    for(; num_bytes>0; num_bytes--) {
506*593dc095SDavid du Colombier 	        dp[num_bytes] = (byte)data;
507*593dc095SDavid du Colombier 		data >>= 8;
5087dd7cddfSDavid du Colombier 	    }
5097dd7cddfSDavid du Colombier 	}
5107dd7cddfSDavid du Colombier     }
5117dd7cddfSDavid du Colombier     *pcolor = color;
5127dd7cddfSDavid du Colombier     return 0;
5137dd7cddfSDavid du Colombier }
5147dd7cddfSDavid du Colombier 
515*593dc095SDavid du Colombier 
5167dd7cddfSDavid du Colombier /* Put out a command to set the tile colors. */
5177dd7cddfSDavid du Colombier int
cmd_set_tile_colors(gx_device_clist_writer * cldev,gx_clist_state * pcls,gx_color_index color0,gx_color_index color1)5187dd7cddfSDavid du Colombier cmd_set_tile_colors(gx_device_clist_writer * cldev, gx_clist_state * pcls,
5197dd7cddfSDavid du Colombier 		    gx_color_index color0, gx_color_index color1)
5207dd7cddfSDavid du Colombier {
5217dd7cddfSDavid du Colombier     int code = 0;
5227dd7cddfSDavid du Colombier 
5237dd7cddfSDavid du Colombier     if (color0 != pcls->tile_colors[0]) {
5247dd7cddfSDavid du Colombier 	code = cmd_put_color(cldev, pcls,
5257dd7cddfSDavid du Colombier 			     &clist_select_tile_color0,
5267dd7cddfSDavid du Colombier 			     color0, &pcls->tile_colors[0]);
5277dd7cddfSDavid du Colombier 	if (code != 0)
5287dd7cddfSDavid du Colombier 	    return code;
5297dd7cddfSDavid du Colombier     }
5307dd7cddfSDavid du Colombier     if (color1 != pcls->tile_colors[1])
5317dd7cddfSDavid du Colombier 	code = cmd_put_color(cldev, pcls,
5327dd7cddfSDavid du Colombier 			     &clist_select_tile_color1,
5337dd7cddfSDavid du Colombier 			     color1, &pcls->tile_colors[1]);
5347dd7cddfSDavid du Colombier     return code;
5357dd7cddfSDavid du Colombier }
5367dd7cddfSDavid du Colombier 
5377dd7cddfSDavid du Colombier /* Put out a command to set the tile phase. */
5387dd7cddfSDavid du Colombier int
cmd_set_tile_phase(gx_device_clist_writer * cldev,gx_clist_state * pcls,int px,int py)5397dd7cddfSDavid du Colombier cmd_set_tile_phase(gx_device_clist_writer * cldev, gx_clist_state * pcls,
5407dd7cddfSDavid du Colombier 		   int px, int py)
5417dd7cddfSDavid du Colombier {
5427dd7cddfSDavid du Colombier     int pcsize;
5437dd7cddfSDavid du Colombier     byte *dp;
5447dd7cddfSDavid du Colombier     int code;
5457dd7cddfSDavid du Colombier 
5467dd7cddfSDavid du Colombier     pcsize = 1 + cmd_size2w(px, py);
5477dd7cddfSDavid du Colombier     code =
5487dd7cddfSDavid du Colombier 	set_cmd_put_op(dp, cldev, pcls, (byte)cmd_opv_set_tile_phase, pcsize);
5497dd7cddfSDavid du Colombier     if (code < 0)
5507dd7cddfSDavid du Colombier 	return code;
5517dd7cddfSDavid du Colombier     ++dp;
5527dd7cddfSDavid du Colombier     pcls->tile_phase.x = px;
5537dd7cddfSDavid du Colombier     pcls->tile_phase.y = py;
5547dd7cddfSDavid du Colombier     cmd_putxy(pcls->tile_phase, dp);
5557dd7cddfSDavid du Colombier     return 0;
5567dd7cddfSDavid du Colombier }
5577dd7cddfSDavid du Colombier 
5587dd7cddfSDavid du Colombier /* Write a command to enable or disable the logical operation. */
5597dd7cddfSDavid du Colombier int
cmd_put_enable_lop(gx_device_clist_writer * cldev,gx_clist_state * pcls,int enable)5607dd7cddfSDavid du Colombier cmd_put_enable_lop(gx_device_clist_writer * cldev, gx_clist_state * pcls,
5617dd7cddfSDavid du Colombier 		   int enable)
5627dd7cddfSDavid du Colombier {
5637dd7cddfSDavid du Colombier     byte *dp;
5647dd7cddfSDavid du Colombier     int code = set_cmd_put_op(dp, cldev, pcls,
5657dd7cddfSDavid du Colombier 			      (byte)(enable ? cmd_opv_enable_lop :
5667dd7cddfSDavid du Colombier 				     cmd_opv_disable_lop),
5677dd7cddfSDavid du Colombier 			      1);
5687dd7cddfSDavid du Colombier 
5697dd7cddfSDavid du Colombier     if (code < 0)
5707dd7cddfSDavid du Colombier 	return code;
5717dd7cddfSDavid du Colombier     pcls->lop_enabled = enable;
5727dd7cddfSDavid du Colombier     return 0;
5737dd7cddfSDavid du Colombier }
5747dd7cddfSDavid du Colombier 
5757dd7cddfSDavid du Colombier /* Write a command to enable or disable clipping. */
5767dd7cddfSDavid du Colombier /* This routine is only called if the path extensions are included. */
5777dd7cddfSDavid du Colombier int
cmd_put_enable_clip(gx_device_clist_writer * cldev,gx_clist_state * pcls,int enable)5787dd7cddfSDavid du Colombier cmd_put_enable_clip(gx_device_clist_writer * cldev, gx_clist_state * pcls,
5797dd7cddfSDavid du Colombier 		    int enable)
5807dd7cddfSDavid du Colombier {
5817dd7cddfSDavid du Colombier     byte *dp;
5827dd7cddfSDavid du Colombier     int code = set_cmd_put_op(dp, cldev, pcls,
5837dd7cddfSDavid du Colombier 			      (byte)(enable ? cmd_opv_enable_clip :
5847dd7cddfSDavid du Colombier 				     cmd_opv_disable_clip),
5857dd7cddfSDavid du Colombier 			      1);
5867dd7cddfSDavid du Colombier 
5877dd7cddfSDavid du Colombier     if (code < 0)
5887dd7cddfSDavid du Colombier 	return code;
5897dd7cddfSDavid du Colombier     pcls->clip_enabled = enable;
5907dd7cddfSDavid du Colombier     return 0;
5917dd7cddfSDavid du Colombier }
5927dd7cddfSDavid du Colombier 
5937dd7cddfSDavid du Colombier /* Write a command to set the logical operation. */
5947dd7cddfSDavid du Colombier int
cmd_set_lop(gx_device_clist_writer * cldev,gx_clist_state * pcls,gs_logical_operation_t lop)5957dd7cddfSDavid du Colombier cmd_set_lop(gx_device_clist_writer * cldev, gx_clist_state * pcls,
5967dd7cddfSDavid du Colombier 	    gs_logical_operation_t lop)
5977dd7cddfSDavid du Colombier {
5987dd7cddfSDavid du Colombier     byte *dp;
5997dd7cddfSDavid du Colombier     uint lop_msb = lop >> 6;
6007dd7cddfSDavid du Colombier     int code = set_cmd_put_op(dp, cldev, pcls,
6017dd7cddfSDavid du Colombier 			      cmd_opv_set_misc, 2 + cmd_size_w(lop_msb));
6027dd7cddfSDavid du Colombier 
6037dd7cddfSDavid du Colombier     if (code < 0)
6047dd7cddfSDavid du Colombier 	return code;
6057dd7cddfSDavid du Colombier     dp[1] = cmd_set_misc_lop + (lop & 0x3f);
6067dd7cddfSDavid du Colombier     cmd_put_w(lop_msb, dp + 2);
6077dd7cddfSDavid du Colombier     pcls->lop = lop;
6087dd7cddfSDavid du Colombier     return 0;
6097dd7cddfSDavid du Colombier }
6107dd7cddfSDavid du Colombier 
6117dd7cddfSDavid du Colombier /* Disable (if default) or enable the logical operation, setting it if */
6127dd7cddfSDavid du Colombier /* needed. */
6137dd7cddfSDavid du Colombier int
cmd_update_lop(gx_device_clist_writer * cldev,gx_clist_state * pcls,gs_logical_operation_t lop)6147dd7cddfSDavid du Colombier cmd_update_lop(gx_device_clist_writer *cldev, gx_clist_state *pcls,
6157dd7cddfSDavid du Colombier 	       gs_logical_operation_t lop)
6167dd7cddfSDavid du Colombier {
6177dd7cddfSDavid du Colombier     int code;
6187dd7cddfSDavid du Colombier 
6197dd7cddfSDavid du Colombier     if (lop == lop_default)
6207dd7cddfSDavid du Colombier 	return cmd_disable_lop(cldev, pcls);
6217dd7cddfSDavid du Colombier     code = cmd_set_lop(cldev, pcls, lop);
6227dd7cddfSDavid du Colombier     if (code < 0)
6237dd7cddfSDavid du Colombier 	return code;
6247dd7cddfSDavid du Colombier     return cmd_enable_lop(cldev, pcls);
6257dd7cddfSDavid du Colombier }
6267dd7cddfSDavid du Colombier 
6277dd7cddfSDavid du Colombier /* Write a parameter list */
6287dd7cddfSDavid du Colombier int	/* ret 0 all ok, -ve error */
cmd_put_params(gx_device_clist_writer * cldev,gs_param_list * param_list)6297dd7cddfSDavid du Colombier cmd_put_params(gx_device_clist_writer *cldev,
6307dd7cddfSDavid du Colombier 	       gs_param_list *param_list) /* NB open for READ */
6317dd7cddfSDavid du Colombier {
6327dd7cddfSDavid du Colombier     byte *dp;
6337dd7cddfSDavid du Colombier     int code;
6347dd7cddfSDavid du Colombier     byte local_buf[512];	/* arbitrary */
6357dd7cddfSDavid du Colombier     int param_length;
6367dd7cddfSDavid du Colombier 
6377dd7cddfSDavid du Colombier     /* Get serialized list's length + try to get it into local var if it fits. */
6387dd7cddfSDavid du Colombier     param_length = code =
6397dd7cddfSDavid du Colombier 	gs_param_list_serialize(param_list, local_buf, sizeof(local_buf));
6407dd7cddfSDavid du Colombier     if (param_length > 0) {
6417dd7cddfSDavid du Colombier 	/* Get cmd buffer space for serialized */
642*593dc095SDavid du Colombier 	code = set_cmd_put_all_op(dp, cldev, cmd_opv_extend,
643*593dc095SDavid du Colombier 				  2 + sizeof(unsigned) + param_length);
6447dd7cddfSDavid du Colombier 	if (code < 0)
6457dd7cddfSDavid du Colombier 	    return code;
6467dd7cddfSDavid du Colombier 
6477dd7cddfSDavid du Colombier 	/* write param list to cmd list: needs to all fit in cmd buffer */
6487dd7cddfSDavid du Colombier 	if_debug1('l', "[l]put_params, length=%d\n", param_length);
649*593dc095SDavid du Colombier 	dp[1] = cmd_opv_ext_put_params;
650*593dc095SDavid du Colombier 	dp += 2;
6517dd7cddfSDavid du Colombier 	memcpy(dp, &param_length, sizeof(unsigned));
6527dd7cddfSDavid du Colombier 	dp += sizeof(unsigned);
6537dd7cddfSDavid du Colombier 	if (param_length > sizeof(local_buf)) {
6547dd7cddfSDavid du Colombier 	    int old_param_length = param_length;
6557dd7cddfSDavid du Colombier 
6567dd7cddfSDavid du Colombier 	    param_length = code =
6577dd7cddfSDavid du Colombier 		gs_param_list_serialize(param_list, dp, old_param_length);
6587dd7cddfSDavid du Colombier 	    if (param_length >= 0)
6597dd7cddfSDavid du Colombier 		code = (old_param_length != param_length ?
6607dd7cddfSDavid du Colombier 			gs_note_error(gs_error_unknownerror) : 0);
6617dd7cddfSDavid du Colombier 	    if (code < 0) {
6627dd7cddfSDavid du Colombier 		/* error serializing: back out by writing a 0-length parm list */
6637dd7cddfSDavid du Colombier 		memset(dp - sizeof(unsigned), 0, sizeof(unsigned));
6647dd7cddfSDavid du Colombier 		cmd_shorten_list_op(cldev, &cldev->band_range_list,
6657dd7cddfSDavid du Colombier 				    old_param_length);
6667dd7cddfSDavid du Colombier 	    }
6677dd7cddfSDavid du Colombier 	} else
6687dd7cddfSDavid du Colombier 	    memcpy(dp, local_buf, param_length);	    /* did this when computing length */
6697dd7cddfSDavid du Colombier     }
6707dd7cddfSDavid du Colombier     return code;
6717dd7cddfSDavid du Colombier }
6723ff48bf5SDavid du Colombier 
6733ff48bf5SDavid du Colombier /* Initialize CCITTFax filters. */
6743ff48bf5SDavid du Colombier private void
clist_cf_init(stream_CF_state * ss,int width)6753ff48bf5SDavid du Colombier clist_cf_init(stream_CF_state *ss, int width)
6763ff48bf5SDavid du Colombier {
6773ff48bf5SDavid du Colombier     ss->K = -1;
6783ff48bf5SDavid du Colombier     ss->Columns = width;
6793ff48bf5SDavid du Colombier     ss->EndOfBlock = false;
6803ff48bf5SDavid du Colombier     ss->BlackIs1 = true;
6813ff48bf5SDavid du Colombier     ss->DecodedByteAlign = align_bitmap_mod;
6823ff48bf5SDavid du Colombier }
6833ff48bf5SDavid du Colombier void
clist_cfe_init(stream_CFE_state * ss,int width,gs_memory_t * mem)6843ff48bf5SDavid du Colombier clist_cfe_init(stream_CFE_state *ss, int width, gs_memory_t *mem)
6853ff48bf5SDavid du Colombier {
6863ff48bf5SDavid du Colombier     s_init_state((stream_state *)ss, &s_CFE_template, mem);
6873ff48bf5SDavid du Colombier     s_CFE_set_defaults_inline(ss);
6883ff48bf5SDavid du Colombier     clist_cf_init((stream_CF_state *)ss, width);
6893ff48bf5SDavid du Colombier     s_CFE_template.init((stream_state *)(ss));
6903ff48bf5SDavid du Colombier }
6913ff48bf5SDavid du Colombier void
clist_cfd_init(stream_CFD_state * ss,int width,int height,gs_memory_t * mem)6923ff48bf5SDavid du Colombier clist_cfd_init(stream_CFD_state *ss, int width, int height, gs_memory_t *mem)
6933ff48bf5SDavid du Colombier {
6943ff48bf5SDavid du Colombier     s_init_state((stream_state *)ss, &s_CFD_template, mem);
6953ff48bf5SDavid du Colombier     s_CFD_template.set_defaults((stream_state *)ss);
6963ff48bf5SDavid du Colombier     clist_cf_init((stream_CF_state *)ss, width);
6973ff48bf5SDavid du Colombier     ss->Rows = height;
6983ff48bf5SDavid du Colombier     s_CFD_template.init((stream_state *)(ss));
6993ff48bf5SDavid du Colombier }
7003ff48bf5SDavid du Colombier 
7013ff48bf5SDavid du Colombier /* Initialize RunLength filters. */
7023ff48bf5SDavid du Colombier void
clist_rle_init(stream_RLE_state * ss)7033ff48bf5SDavid du Colombier clist_rle_init(stream_RLE_state *ss)
7043ff48bf5SDavid du Colombier {
7053ff48bf5SDavid du Colombier     s_init_state((stream_state *)ss, &s_RLE_template, (gs_memory_t *)0);
7063ff48bf5SDavid du Colombier     s_RLE_set_defaults_inline(ss);
7073ff48bf5SDavid du Colombier     s_RLE_init_inline(ss);
7083ff48bf5SDavid du Colombier }
7093ff48bf5SDavid du Colombier void
clist_rld_init(stream_RLD_state * ss)7103ff48bf5SDavid du Colombier clist_rld_init(stream_RLD_state *ss)
7113ff48bf5SDavid du Colombier {
7123ff48bf5SDavid du Colombier     s_init_state((stream_state *)ss, &s_RLD_template, (gs_memory_t *)0);
7133ff48bf5SDavid du Colombier     s_RLD_set_defaults_inline(ss);
7143ff48bf5SDavid du Colombier     s_RLD_init_inline(ss);
7153ff48bf5SDavid du Colombier }
716