/* Copyright (C) 1991, 1995 Aladdin Enterprises.  All rights reserved.
  
  This file is part of Aladdin Ghostscript.
  
  Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  or distributor accepts any responsibility for the consequences of using it,
  or for whether it serves any particular purpose or works at all, unless he
  or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  License (the "License") for full details.
  
  Every copy of Aladdin Ghostscript must include a copy of the License,
  normally in a plain ASCII text file named PUBLIC.  The License grants you
  the right to copy, modify and redistribute Aladdin Ghostscript, but only
  under certain conditions described in the License.  Among other things, the
  License requires that the copyright notice and this notice be preserved on
  all copies.
*/

/* gxclist.h */
/* Command list definitions for Ghostscript. */
/* Requires gxdevice.h and gxdevmem.h */
#include "gxclio.h"

/*
 * A command list is essentially a compressed list of driver calls.
 * Command lists are used to record an image that must be rendered in bands
 * for high-resolution and/or limited-memory printers.
 *
 * Command lists work in two phases.  The first phase records driver calls,
 * sorting them according to the band(s) they affect.  The second phase
 * reads back the commands band-by-band to create the bitmap images.
 */

/*
 * The command list contains both commands for particular bands (the vast
 * majority) and commands that apply to all bands.  In order to synchronize
 * the two, we maintain the following invariant for buffered commands:
 *
 *	If there are any all-band commands in the buffer, they are the
 *	first commands in the buffer, before any specific-band commands.
 *
 * To maintain this invariant, whenever we are about to put an all-band
 * command in the buffer, we check to see if the buffer already has any
 * all-band commands in it, and if so, whether they are the last commands
 * in the buffer; if the answer to either question is negative, we flush
 * the buffer.
 */

/*
 * Currently, halftoning occurs during the first phase, producing calls
 * to tile_rectangle.  Both phases keep a cache of recently seen
 * halftone cells, which allows writing only a short cache index in the
 * command list rather than the entire bitmap.  In this cache, we keep
 * the entire (possibly replicated) cell if there is room for all of them,
 * otherwise only the unreplicated cell (or only replicated horizontally,
 * and no more than will fit in the width of align_bitmap_mod bytes).
 * The first phase makes all the decisions about this.
 *
 * We keep only a single cache for all bands, but since the second phase
 * reads the command lists for each band separately, we have to keep track
 * for each cache entry E and band B whether the definition of E has been
 * written into B's list.  We do this with a bit mask in each entry.
 *
 * Eventually, we will replace this entire arrangement with one in which
 * we pass the actual halftone screen (whitening order) to ALL bands
 * through the command list, and halftoning occurs on the second phase.
 * This not only will shrink the command list, but will allow us to apply
 * other rendering algorithms such as error diffusion in the second phase.
 */
typedef struct {
	int slot_index;
} tile_hash;
typedef struct {
	gx_bitmap_id id;
	/* byte band_mask[]; */
	/* byte bits[]; */
} tile_slot;

/* Define the prefix on each command run in the writing buffer. */
typedef struct cmd_prefix_s cmd_prefix;
struct cmd_prefix_s {
	cmd_prefix *next;
	uint size;
};

/* Define the pointers for managing a list of command runs in the buffer. */
/* There is one of these for each band, plus one for all-band commands. */
typedef struct cmd_list_s {
	cmd_prefix *head, *tail;	/* list of commands for band */
} cmd_list;

/*
 * Define the main structure for holding command list state.
 * Unless otherwise noted, all elements are used in both the writing (first)
 * and reading (second) phase.
 */
typedef struct gx_device_clist_s gx_device_clist;
typedef struct gx_clist_state_s gx_clist_state;
struct gx_device_clist_s {
	gx_device_forward_common;	/* (see gxdevice.h) */
		/* Following must be set before writing or reading. */
	/* gx_device *target; */	/* device for which commands */
					/* are being buffered */
	byte *data;			/* buffer area */
	uint data_size;			/* size of buffer */
	clist_file_ptr cfile;		/* command list file */
	clist_file_ptr bfile;		/* command list block file */
		/* Following are used for both writing and reading. */
	byte *tile_data;		/* data for cached tiles */
	uint tile_data_size;		/* total size of tile cache data */
	uint tile_slot_size;		/* size of each slot in tile cache */
	int tile_depth;			/* depth of current tile (1 or */
					/* dev->color_info.depth) */
#define tile_slot_ptr(cldev,index)\
  (tile_slot *)((cldev)->tile_data + (index) * (cldev)->tile_slot_size)
#define ts_mask(pts) (byte *)((pts) + 1)
#define ts_bits(cldev,pts) (ts_mask(pts) + (cldev)->tile_band_mask_size)
		/* Following are set when writing, read when reading. */
	int band_height;		/* height of each band */
	int nbands;			/* # of bands */
	long bfile_end_pos;		/* ftell at end of bfile */
		/* Following are used only when writing. */
	int error_code;			/* error returned by cmd_put_op */
	gx_clist_state *states;		/* current state of each band */
	byte *cbuf;			/* start of command buffer */
	byte *cnext;			/* next slot in command buffer */
	byte *cend;			/* end of command buffer */
	cmd_list *ccl;			/* &clist_state.list of last command */
	cmd_list all_bands;		/* list of all-band commands */
		/* Following is the tile cache, used only when writing. */
	gx_tile_bitmap tile;		/* current tile cache parameters */
					/* (data pointer & id not used) */
	tile_hash *tile_hash_table;	/* hash table for tile cache: */
					/* -1 = unused, >= 0 = slot index */
	uint tile_max_size;		/* max size of a single tile (bytes) */
	uint tile_hash_mask;		/* size of tile hash table -1 */
	uint tile_band_mask_size;	/* size of band mask preceding */
					/* each tile in the cache */
	uint tile_count;		/* # of occupied entries in cache */
	uint tile_max_count;		/* capacity of the cache */
		/* Following are used only when reading. */
	int ymin, ymax;			/* current band */
	gx_device_memory mdev;
};
/* The device template itself is never used, only the procs. */
extern gx_device_procs gs_clist_device_procs;
