1 /******************************************************************************
2   File:     $Id: gdeveprn.h,v 1.23 2001/04/30 05:15:51 Martin Rel $
3   Contents: Header file for the abstract ghostscript device 'eprn'
4   Author:   Martin Lottermoser, Greifswaldstrasse 28, 38124 Braunschweig,
5             Germany; e-mail: Martin.Lottermoser@t-online.de.
6 
7 *******************************************************************************
8 *									      *
9 *	Copyright (C) 2000, 2001 by Martin Lottermoser			      *
10 *	All rights reserved						      *
11 *									      *
12 *******************************************************************************
13 
14   The 'eprn' device
15   *****************
16   In developing my hpdj/pcl3 driver for PCL 3+ I had to implement a lot of
17   functionality which was logically independent of PCL. This indicated that the
18   functionality offered by ghostscript's 'prn' device was insufficient and
19   should be extended, leading to this "extended prn device".
20 
21   Functionality
22   =============
23   The "eprn" device offers the following services to derived devices:
24   - A simple but still flexible rendering model. A derived device defines
25     printer capability descriptions listing the supported rendering parameters,
26     lets the eprn device handle the user's rendering requests, and then just
27     fetches the pixels.
28   - A PostScript-conforming initialization of default user space with respect
29     to landscape orientation and support for the standard page device parameter
30     "LeadingEdge".
31   - Recognition of media sizes from the document and checking of supported
32     sizes based on printer descriptions
33   - Flexible handling of size-specific hardware margins
34   - Counting of pages printed across gs invocations by means of page count
35     files
36 
37   Rendering Model
38   ===============
39   The "eprn" device parameterizes the printer's rendering capabilities as
40   follows:
41   - process colour model (Gray, RGB, CMY, CMY+K, CMYK)
42   - resolution in horizontal and vertical directions
43   - number of intensity levels per colorant, chosen independently for black
44     and non-black (RGB or CMY) colorants.
45   In addition, the rendering process as implemented in this driver is
46   parameterized by:
47   - method for rendering intensities (printer, halftones or error diffusion)
48   These parameters are specified by the user. The device checks whether the
49   printer supports the requested combination and, if it does, sets
50   ghostscript's internal data structures accordingly.
51 
52   The derived device can obtain the resulting pixels by successively calling
53   eprn_get_planes() from the page printing procedure.
54 
55   Device Coordinates
56   ==================
57   "Pixmap device space" is the coordinate system used by the "prn" device for
58   generating a pixmap and implicit in the API for accessing it (e.g.,
59   gdev_prn_copy_scan_lines()). In identifying the directions "left", "bottom",
60   "right" and "top" I'm assuming that the x axis is pointing to the right and
61   the y axis downwards. This is not concerned with the orientation of device
62   space on a sheet printed but is merely a definition of what, e.g., "down"
63   means for the eprn device: it is defined as "towards increasing prn y values".
64   This makes the code more readable for the case where the real device
65   coordinate system (on the sheet) has just this orientation. Too bad for the
66   others :-).
67 
68   Terms like "width" and "height" are also defined with respect to this
69   interpretation, i.e., "width" is an extension in x direction.
70 
71   Note that names and interpretations of some of ghostscript's standard
72   device structure fields (like 'width', 'height') are also based on this
73   convention although this is not explicitly stated. This does however not
74   apply to all parameters: for example, HWMargins[] and MediaSize[] are to be
75   interpreted in default user space (see gx_default_clip_box()).
76 
77   One key assumption of the eprn device is that the top edge of pixmap device
78   space is the edge closest to and parallel with the medium's leading edge.
79   It is the responsibility of the derived device to ensure this. Usually
80   it means that raster lines have to be printed in the order of ascending y.
81   (The eprn device will work if the derived device violates this condition, but
82   the meaning of user-visible properties of the device would change.)
83 
84   The device sets up the device coordinate system such that the device space
85   origin is the top left corner of the imageable area where "top" and "left"
86   refer to you holding the sheet with the printed side towards you and the
87   leading edge at the top. Units and directions are identical with pixmap
88   device space.
89 
90   Page Descriptions
91   =================
92   When a PostScript document requests a particular page size by specifying its
93   width and height in default user space the eprn device combines this
94   information with certain conditions imposed by the derived device and looks
95   for a matching page description entry in the printer's capability
96   description. The following information from such an entry is needed for
97   correctly setting up the relation between default user space and device space:
98 
99     - default orientation of the sheet in pixmap device space
100       (MS_TRANSVERSE_FLAG; set iff the sheet has width > height in pixmap
101       device space)
102     - hardware margins
103 
104   This part is interpreted by the eprn device.
105 
106   In addition, a page description entry may contain a number of flags
107   indicating special conditions under which this entry is to be selected or
108   carrying information on how to configure the printer. The flags are those
109   defined by mediasize.h (except that MS_TRANSVERSE_FLAG and MS_ROTATED_FLAG
110   may not be used for this purpose), their interpretation is up to the derived
111   device which must request them or to which they will become visible when the
112   entry is selected.
113 
114   The eprn device takes the following items as the request to be matched with a
115   page description entry in the printer's capability description:
116 
117     - the media size of the document and, if set, the "LeadingEdge" page device
118       parameter
119     - a pattern of desired (not necessarily *required*) flags
120     - an ordered list of optional flags
121 
122   Media size and LeadingEdge are set via PostScript or the command line, the
123   flags can be set by the derived device through its device structure instance
124   or by calling eprn_set_media_flags(). The optional flags when combined with
125   the bitwise OR effectively define a mask of bits which may be ignored when
126   checking whether an entry matches the desired flags. The order of optional
127   flags is from most to least desirable to ignore.
128 
129   The complete request is compared to the list of page descriptions as follows:
130 
131    1. If the media size, irrespective of flags, cannot be matched at 5 bp
132       tolerance, the request fails with an error message to standard error.
133    2. Otherwise a shortened list containing all entries having a matching
134       size is compiled, at least conceptually. If the device supports custom
135       page sizes, they are listed at the end. This is the "base list".
136    3. If LeadingEdge is not null, the MS_TRANSVERSE_FLAG is set or cleared
137       accordingly in the pattern of desired flags. This flag is also always
138       added to the front of the list of optional flags.
139    4. A mask of flags to be ignored is set to zero.
140    5. The base list is searched for an entry agreeing with the desired flags
141       except possibly for those in the ignore mask.
142    6. If no such entry is found, the next flag in the list of optional flags is
143       added to the ignore mask and execution continues with step 5. If there is
144       no such flag, the request fails and the flag mismatch reporting function
145       is called (see below).
146    7. If a matching entry is found the list of optional flags is processed
147       backwards starting with the flag before the last one added to the ignore
148       mask. For each such flag an attempt is made to remove it from the mask.
149       If there still is at least one matching entry in the base list the flag
150       remains cleared, otherwise it is put back into the mask.
151    8. Finally, the first entry matching the request mask and the current
152       ignore mask will be selected:
153       - its media code will be made available to the derived device in the
154         eprn device's 'code' field,
155       - the hardware margins will be set from the page description (unless the
156         user has explicitly specified a value for the ".HWMargins" page device
157         parameter),
158       - default user space will be configured based on sheet orientation
159         (transverse or not in device space) and page orientation (portrait or
160         landscape in default user space).
161 
162   Because the error message in step 6 has to report a mismatch on the flags
163   and because the interpretation of the flags is fixed by the derived device,
164   an error message issued by the eprn device may not be particularly
165   illuminating to the user (the user will usually think in terms of the
166   interpretation the derived device associates with these flags). Therefore
167   issuing this error message can be delegated to a function ("flag mismatch
168   reporting function") specified by the derived device in its device structure
169   instance.
170 
171 ******************************************************************************/
172 
173 #ifndef _gdeveprn_h	/* Inclusion protection */
174 #define _gdeveprn_h
175 
176 /* Configuration management identification */
177 #pragma ident "@(#)$Id: gdeveprn.h,v 1.23 2001/04/30 05:15:51 Martin Rel $"
178 
179 /*****************************************************************************/
180 
181 /* Special Aladdin header, must be included before <sys/types.h> on some
182    platforms (e.g., FreeBSD). This necessity seems to be triggered for example
183    by <stdio.h>. */
184 #include "std.h"
185 
186 /* Standard headers */
187 #include <stdio.h>	/* for 'FILE' and 'size_t' */
188 
189 /* Ghostscript headers */
190 #include "gdevprn.h"
191 /* This header is assumed to include a definition for 'bool' (stdpre.h). */
192 
193 /* Other header files */
194 #include "mediasize.h"
195 
196 /*****************************************************************************/
197 
198 /*  Types to describe supported page sizes and associated setup information.
199     All sizes are in bp and all orientations refer to pixmap device space.
200  */
201 
202 /* Discrete page sizes */
203 typedef struct {
204   ms_MediaCode code;
205    /* The media flags in 'code' identify the conditions under which the size
206       is supported ("required flags") and carry information needed in order
207       to adapt ghostscript or the printer to using this entry ("optional
208       flags"). The distinction between the two groups of flags is fixed by the
209       derived device when calling eprn_set_media_flags() except that special
210       rules apply to MS_TRANSVERSE_FLAG which is handled by eprn.
211       Setting MS_TRANSVERSE_FLAG indicates that media of this size are normally
212       fed such that width > height in pixmap device space, otherwise
213       width <= height is assumed.
214       Setting MS_ROTATED_FLAG is not permitted.
215       The interpretation of all other flags is up to the derived device.
216     */
217   float left, bottom, right, top;
218    /* Hardware margins (non-negative) in bp */
219 } eprn_PageDescription;
220 
221 /* Custom page sizes */
222 typedef struct {
223   /*  The first two lines have the same meaning as for 'eprn_PageDescription'.
224       However, apart from flags, the 'code' field must be 'ms_CustomPageSize'.
225   */
226   ms_MediaCode code;
227   float left, bottom, right, top;
228   float width_min, width_max, height_min, height_max;
229    /* Permissible range in bp for width and height when a sheet's dimension is
230       given such that width <= height. */
231 } eprn_CustomPageDescription;
232 
233 /*
234   Here follows an example of using "eprn_PageDescription". It describes a
235   printer supporting A4 and US Letter, the first with 5 mm margins, the latter
236   with 0.2 inches:
237 
238     const eprn_PageDescription page_description[] = {
239         {ms_A4,       5*BP_PER_MM,   5*BP_PER_MM,   5*BP_PER_MM,   5*BP_PER_MM},
240         {ms_Letter, 0.2*BP_PER_IN, 0.2*BP_PER_IN, 0.2*BP_PER_IN, 0.2*BP_PER_IN},
241         {ms_none, 0, 0, 0, 0}
242       };
243 
244   The last entry is a sentinel value which will be required later.
245 
246 ******************************************************************************/
247 
248 /*  Types to describe supported combinations of resolutions, process colour
249     models and intensity levels per colorant
250 
251     These types often contain pointers to lists terminated with a sentinel
252     value. As these are usually static data, this makes it easier to share data
253     between printer descriptions.
254  */
255 
256 /* Process colour models */
257 typedef enum {
258   eprn_DeviceGray,
259   eprn_DeviceRGB,
260   eprn_DeviceCMY,
261   eprn_DeviceCMY_plus_K,
262    /* 'eprn_DeviceCMY_plus_K' is a process colour model using the CMYK
263       colorants but never mixing black with one of the others. The underlying
264       native colour space is 'DeviceRGB'. */
265   eprn_DeviceCMYK
266 } eprn_ColourModel;
267 
268 /* Horizontal and vertical resolutions w.r.t. pixmap device space */
269 typedef struct {
270   float h, v;
271 } eprn_Resolution;
272 
273 /* Range for the number of intensity levels */
274 typedef struct {
275   unsigned short from, to;	/* both inclusive */
276 } eprn_IntensityLevels;
277 
278 /* Combined resolutions and intensities. Any combination of the listed
279    resolutions and the listed intensity levels is permitted. */
280 typedef struct {
281   const eprn_Resolution *resolutions;
282    /* either NULL (all resolutions are accepted) or a list terminated with
283       a {0.0, 0.0} entry */
284   const eprn_IntensityLevels *levels;
285    /* non-NULL; this list is terminated with {0, 0}. The variable is a list in
286       order to permit easier specification of discrete levels. */
287 } eprn_ResLev;
288 
289 /* A complete instance of a rendering capability entry */
290 typedef struct {
291   eprn_ColourModel colour_model;
292    /* A value of 'eprn_DeviceCMYK' implies the capability for
293       'eprn_DeviceCMY_plus_K' because the difference is realized in this driver
294       and is not part of the printer's capabilities.
295       In contrast, 'eprn_DeviceCMY_plus_K' or 'eprn_DeviceCMYK' do *not* imply
296       the capability for CMY or Gray! This is because we assume that
297       'colour_model' corresponds to particular hardware settings for the
298       printer.
299     */
300   const eprn_ResLev *info[2];
301    /* Supported resolutions and intensities indexed by colorant. The first
302       entry refers to black except for eprn_DeviceRGB and eprn_DeviceCMY when
303       it describes the three non-black colorants. The second entry is ignored
304       unless both black and non-black colorants are used in which case it can
305       either refer to the latter or be NULL to indicate that the black entry
306       applies also to the non-black colorants.
307       Any non-null info[] points to a list terminated with a {NULL, NULL} entry.
308       Only values for those colorants described by different (non-NULL) 'info'
309       entries in an instance of this type can be chosen independently. Hence at
310       most black can have values different from those of the other colorants.
311     */
312 } eprn_ColourInfo;
313 
314 /*
315   As an example application of these types, consider a bilevel device
316   supporting 600 ppi monochrome printing:
317 
318     const eprn_Resolution sixhundred[] = { {600, 600}, {0, 0}};
319     const eprn_IntensityLevels bilevel[] = { {2, 2}, {0, 0}};
320     const eprn_ResLev rl_600_2[] = { {sixhundred, bilevel}, {NULL, NULL}};
321     const eprn_ColourInfo mono_600_2[] = {
322         {eprn_DeviceGray, {rl_600_2, NULL}},
323         {eprn_DeviceGray, {NULL, NULL}}
324       };
325 
326 ******************************************************************************/
327 
328 /* Printer capability description */
329 typedef struct {
330   const char *name;
331    /* This string is used in error messages generated by the device. It should
332       describe the printer, not a gs device. In selecting an appropriate value
333       imagine a statement like "... is not supported by the <name>" or "The
334       <name> does not support ...".
335     */
336 
337   /* Media sizes and hardware margins */
338   const eprn_PageDescription *sizes;
339   /*  List of supported discrete media sizes and associated hardware margins,
340       terminated by an entry with 'code' == ms_none. This must always be
341       non-NULL. */
342   const eprn_CustomPageDescription *custom;
343   /*  This may be NULL, in which case the printer does not support custom
344       page sizes. Otherwise it is a list of entries, terminated with an entry
345       having 0.0 for 'width_max'. */
346   float bottom_increment;
347   /*  Change of bottom hardware margin when not printing in DeviceGray,
348       specified in bp. This correction is ignored if the bottom margin is
349       exactly zero.
350       Some HP DeskJets have a larger hardware margin at the bottom for the
351       colour cartridge but this is not the case for banner printing. */
352 
353   /* Colour capabilities */
354   const eprn_ColourInfo *colour_info;
355   /*  List of supported colour models, resolutions and intensity levels.
356       This must always be non-NULL and terminated with an entry having NULL as
357       'info[0]'. There must be at least one 'eprn_ColourInfo' entry permitting
358       identical resolution for all colorants.
359    */
360 } eprn_PrinterDescription;
361 
362 /*
363   To continue our series of examples, here is a complete printer description:
364 
365     const eprn_PrinterDescription description = {
366         "Wrzlbrnf printer", page_description, NULL, 0, mono_600_2
367       };
368 
369 ******************************************************************************/
370 
371 /* Intensity rendering methods */
372 typedef enum {
373   eprn_IR_printer,
374   eprn_IR_halftones,
375   eprn_IR_FloydSteinberg
376 } eprn_IR;
377 
378 /*****************************************************************************/
379 
380 /* Unsigned 8-bit values (should really be 'uint8_t') */
381 typedef unsigned char eprn_Octet;
382 
383 /* Octet strings */
384 typedef struct {
385   eprn_Octet *str;
386   int length;	/* zero or the length in 'eprn_Octet' instances of the area
387                    filled starting at '*str' */
388 } eprn_OctetString;
389 
390 /* Type for flag mismatch reporting function */
391 struct s_eprn_Device;
392  /* The preceding statement is needed in order to establish a forward
393     declaration for "struct s_eprn_Device" at file scope. */
394 typedef void (*eprn_FlagMismatchReporter)(const struct s_eprn_Device *dev,
395                 bool no_match);
396 /*  A function of this kind will be called if the requested media flags cannot
397     be satisfied by the printer although the size itself is supported for some
398     (unspecified) set of flags. The parameter 'no_match' indicates whether the
399     printer supports the set of required flags for some size or not at all
400     (this is intended to be useful in the case of flags denoting printer
401     capabilities). The requested set of media selection flags is available in
402     'dev->eprn.desired_flags' and 'dev->eprn.optional_flags' (MS_ROTATED_FLAG
403     will never be set).
404     The function must write an error message.
405 */
406 
407 /*****************************************************************************/
408 
409 /*  The eprn device variables. These are deliberately defined as a structure
410     and not as usual in ghostscript as a macro body to be inserted into a
411     structure because I want to have namespace isolation for these fields.
412     A derived device may read any of these parameters but should never change
413     them directly. The only exception is 'soft_tumble'.
414  */
415 typedef struct s_eprn_Device {
416   /* Capabilities */
417   const eprn_PrinterDescription *cap;
418    /* non-NULL. The data pointed to may not change unless this is immediately
419       followed by a call to eprn_init_device(). */
420   char *media_file;
421    /* gs_malloc()-allocated media configuration file name.
422       Non-NULL if 'media_overrides' is non-NULL. */
423   eprn_PageDescription *media_overrides;
424    /* A list of supported media dimensions and corresponding hardware margins.
425       This is usually NULL, meaning that 'cap->sizes' and 'cap->custom' should
426       be used.
427       If non-NULL, 'media_overrides' must be terminated with an entry having
428       'code' == ms_none. If this field is non-NULL, only the sizes listed here
429       will be supported. The device will support custom page sizes only if
430       'cap->custom' is not NULL and 'media_overrides' contains an entry for
431       'ms_CustomPageSize'.
432       The pointer refers to gs_malloc()-allocated storage.
433     */
434 
435   /* Page setup */
436   const ms_Flag *flag_desc;
437    /* Description of the additional flags the derived device understands. This
438       can be NULL or a list terminated with an entry having 'code' equal to
439       'ms_none'. */
440   ms_MediaCode
441     desired_flags;
442   const ms_MediaCode
443     *optional_flags;		/* may be NULL; terminated with 'ms_none'. */
444   eprn_FlagMismatchReporter fmr;	/* may be NULL */
445   ms_MediaCode code;
446    /* Page size and other media attributes determined based on printer
447       capabilities. A value of 'ms_none' indicates that the page description
448       entry to be used has not (yet) been successfully identified and that
449       therefore some of the other fields in this structure are not valid. */
450 
451   /* Coordinates */
452   int default_orientation;
453    /* Direction of the positive y axis of default default user space (the
454       requested PageSize had width <= height) as seen from pixmap device space:
455           0	up
456           1	left
457           2	down
458           3	right
459       Hence the value is the number of +90 degrees rotations necessary to
460       obtain the "up" direction of default default user space (positive y axis)
461       from the "up" direction of pixmap device space (negative y axis).
462       The values 0 and 2 imply that the medium has width <= height in pixmap
463       device space, 1 and 3 imply height <= width. */
464   bool leading_edge_set;
465    /* True iff someone set the 'LeadingEdge' page device parameter. In this
466       case its value is stored in 'default_orientation'. The values permitted
467       for 'default_orientation' and their interpretation are chosen such that
468       this gives the desired result.
469       If this value is false, the device will select a value for
470       'default_orientation' based on the MS_TRANSVERSE_FLAG in 'code'. */
471   float
472     right_shift,
473     down_shift;
474      /* Seen from pixmap device space, the top left corner of the sheet is at
475         (-right_shift, -down_shift). Both values are in bp and represent
476         hardware margins, i.e., the origin of pixmap device space is a corner
477         of the sheet's imageable area.
478         These parameters are logically superfluous and could be derived from
479         'HWMargins[]' and possibly other data (like 'default_orientation'),
480         provided one knows what the reference system for 'HWMargins[]' is.
481         This is not documented but it seems to be default user space. In order
482         to have values with a reliable interpretation and because the data are
483         originally given in pixmap device space anyway I have introduced these
484         variables. */
485   bool keep_margins;
486      /* True iff margin information should be taken from 'HWMargins[]' instead
487         of from the printer description. */
488   bool soft_tumble;
489      /* If this field is set, every second page will have its default user
490         coordinate system rotated by 180 degrees. */
491 
492   /* Colour */
493   eprn_ColourModel
494     colour_model;	/* Colour model selected */
495   unsigned int
496     black_levels,	/* Number of intensity levels for black colorant */
497     non_black_levels;	/* Number of intensity levels for non-black colorants */
498   eprn_IR
499     intensity_rendering;  /* method to use */
500 
501   /* Page counting and other spooler support */
502   char
503     *pagecount_file;	/* gs_malloc()-allocated name of page count file.
504                            May be NULL. */
505   bool
506     CUPS_accounting,	/* Send CUPS page accounting messages. */
507     CUPS_messages;	/* Add CUPS message prefixes to error messages and
508                            warnings. */
509 
510   /* Support for the standard page device parameter "MediaPosition" */
511   bool media_position_set;
512   int media_position;
513 
514   /*  Internal parameters. These have reliable values only after a successful
515       call to eprn_open(). */
516   unsigned int
517     bits_per_colorant;	/* Number of bits per colorant used in 'gx_color_index'
518                            values. Constant while the device is open. */
519   eprn_OctetString
520     scan_line,		/* 'str' is gs_malloc()-allocated */
521     next_scan_line;	/* 'str' is gs_malloc()-allocated. Non-null only for
522                            Floyd-Steinberg error diffusion. */
523   unsigned int
524     octets_per_line,	/* Constant while the device is open. */
525     output_planes;	/* Constant while the device is open. */
526   int next_y;		/* During a call to eprn_output_page(), the device y
527     coordinate for the next scan line to fetch from the "prn" device. For
528     eprn_IR_FloydSteinberg, the next scan line to return is actually already
529     present in 'next_scan_line' with its device coordinate being "next_y - 1",
530     unless 'next_y' is zero in which case we have finished. */
531 } eprn_Eprn;
532 
533 /* Macro for device structure type definitions. Note that in contrast to
534    gx_prn_device_common this macro does include the inherited attributes. */
535 #define gx_eprn_device_common						\
536   gx_device_common;		/* Attributes common to all devices */	\
537   gx_prn_device_common;		/* Attributes for all printers */	\
538   eprn_Eprn eprn
539 
540 /* Base type needed for casts */
541 typedef struct {
542   gx_eprn_device_common;
543 } eprn_Device;
544 
545 /*  Macro for initializing device structure instances (device prototypes)
546 
547     This macro corresponds to the prn_device*() macros which are used when
548     basing a device directly on the prn device.
549 
550     The parameters are:
551       dtype:	identifier of the device structure type
552       procs:	pointer to static device procedure table
553                 (const gx_device_procs *, not NULL)
554       dname:	name of the device (const char *, not NULL)
555       xdpi:	horizontal resolution in ppi (float, positive)
556       ydpi:	vertical resolution in ppi (float, positive)
557       print_page:  page printing procedure to be called by
558                 gdev_prn_output_page(), not NULL
559       cap:	pointer to printer capability description
560                 (const eprn_PrinterDescription *, not NULL, the description may
561                 not change until immediately before the next call to
562                 eprn_init_device())
563       flag_desc  description of the non-standard flags the derived device
564                 accepts (const ms_Flag *, may be NULL, otherwise terminated
565                 with an entry having 'ms_none' for 'code')
566       desired	pattern of desired media flags (ms_MediaCode)
567       optional	NULL or a list of optional media flags (const ms_MediaCode *)
568                 terminated with an 'ms_none' value
569       fmr	NULL or pointer to a flag mismatch reporting function
570                 (eprn_FlagMismatchReporter)
571 
572     All storage referred to by pointers remains under the control of the
573     derived device and should not be modified during the lifetime of the
574     device unless explicitly permitted.
575 
576     This macro assumes that it is dealing with a printer supporting at least
577     DeviceGray with 2 intensity levels and the page size described by
578     (DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS), usually US Letter or ISO A4.
579     This is also the initial state. If a derived device wishes to use another
580     initial state, it should define its own macro.
581  */
582 #define eprn_device_initdata(dtype, procs, dname, xdpi, ydpi, print_page, cap, flag_desc, desired, optional, fmr) \
583   prn_device_std_body(			\
584     dtype,				\
585     procs,				\
586     dname,				\
587     DEFAULT_WIDTH_10THS,		\
588     DEFAULT_HEIGHT_10THS,		\
589     xdpi, ydpi,				\
590     0.0, 0.0, 0.0, 0.0, /* margins */	\
591     1,		/* color_info.depth */	\
592     print_page),			\
593   {					\
594     cap,	/* cap */		\
595     NULL,	/* media_file */	\
596     NULL,	/* media_overrides */	\
597     flag_desc,	/* flag_desc */	\
598     desired,	/* desired_flags */	\
599     optional,	/* optional_flags */	\
600     fmr,	/* fmr */		\
601     ms_none,	/* code */		\
602     0,		/* default_orientation */\
603     false,	/* leading_edge_set */	\
604     0.0,	/* right_shift */	\
605     0.0,	/* down_shift */	\
606     false,	/* keep_margins */	\
607     false,	/* soft_tumble */	\
608     eprn_DeviceGray, /* colour_model */	\
609     2,		/* black_levels */	\
610     0,		/* non_black_levels */	\
611     eprn_IR_halftones, /* intensity_rendering */ \
612     NULL,	/* pagecount_file */	\
613     false,	/* CUPS_accounting */	\
614     false,	/* CUPS_messages */	\
615     false,	/* media_position_set */\
616     0,		/* media_position */	\
617     0,		/* bits_per_colorant */	\
618     {NULL, 0},	/* scan_line */		\
619     {NULL, 0},	/* next_scan_line */	\
620     0,		/* octets_per_line */	\
621     0,		/* output_planes */	\
622     0		/* next_y */		\
623   }
624 
625 /*  For the calling conventions of the following functions consult the comments
626     preceding each function's implementation. */
627 
628 /* Initialize the eprn device for another printer model */
629 extern void eprn_init_device(eprn_Device *dev,
630   const eprn_PrinterDescription *desc);
631 
632 /* Modify the information on supported media sizes and associated hardware
633    margins by reading new values from a file */
634 extern int eprn_set_media_data(eprn_Device *dev, const char *media_file,
635   size_t length);
636 
637 /* Set media flags */
638 extern void eprn_set_media_flags(eprn_Device *dev, ms_MediaCode desired,
639   const ms_MediaCode *optional);
640 
641 /*****************************************************************************/
642 
643 /* Device procedures */
644 extern dev_proc_open_device(eprn_open_device);
645 extern dev_proc_get_initial_matrix(eprn_get_initial_matrix);
646 extern dev_proc_output_page(eprn_output_page);
647 extern dev_proc_close_device(eprn_close_device);
648 extern dev_proc_map_rgb_color(eprn_map_rgb_color_for_RGB);
649 extern dev_proc_map_rgb_color(eprn_map_rgb_color_for_RGB_flex);
650 extern dev_proc_map_rgb_color(eprn_map_rgb_color_for_RGB_max);
651 extern dev_proc_map_rgb_color(eprn_map_rgb_color_for_CMY_or_K);
652 extern dev_proc_map_rgb_color(eprn_map_rgb_color_for_CMY_or_K_flex);
653 extern dev_proc_map_rgb_color(eprn_map_rgb_color_for_CMY_or_K_max);
654 extern dev_proc_map_color_rgb(eprn_map_color_rgb);
655 extern dev_proc_get_params(eprn_get_params);
656 extern dev_proc_put_params(eprn_put_params);
657 extern dev_proc_map_cmyk_color(eprn_map_cmyk_color);
658 extern dev_proc_map_cmyk_color(eprn_map_cmyk_color_flex);
659 extern dev_proc_map_cmyk_color(eprn_map_cmyk_color_max);
660 extern dev_proc_map_cmyk_color(eprn_map_cmyk_color_glob);
661 
662 /*  Macro for initializing device procedure tables
663 
664     This macro corresponds to the macro prn_params_procs() which is used when
665     basing a device directly on the prn device.
666 
667     If your device does not need all of the procedures in the argument list,
668     use the following defaults:
669       p_open:		eprn_open_device
670       p_close:		eprn_close_device
671       p_get_params:	eprn_get_params
672       p_put_params:	eprn_put_params
673     On the other hand, if your driver needs its own procedure in any of these
674     cases its code must also call the appropriate default routine.
675 */
676 #define eprn_procs_initdata(p_open, p_close, p_get_params, p_put_params) \
677   p_open,			/* open_device */		\
678   eprn_get_initial_matrix,	/* get_initial_matrix */	\
679   NULL,				/* sync_output */		\
680   eprn_output_page,		/* output_page */		\
681   p_close,			/* close_device */		\
682   eprn_map_rgb_color_for_CMY_or_K,  /* map_rgb_color */		\
683   eprn_map_color_rgb,		/* map_color_rgb */		\
684   NULL,				/* fill_rectangle */		\
685   NULL,				/* tile_rectangle */		\
686   NULL,				/* copy_mono */			\
687   NULL,				/* copy_color */		\
688   NULL,				/* draw_line */			\
689   NULL,				/* get_bits */			\
690   p_get_params,			/* get_params */		\
691   p_put_params,			/* put_params */		\
692   eprn_map_cmyk_color_glob,	/* map_cmyk_color */		\
693   NULL,				/* get_xfont_procs */		\
694   NULL,				/* get_xfont_device */		\
695   NULL,				/* map_rgb_alpha_color */	\
696   gx_page_device_get_page_device  /* get_page_device */
697   /* The remaining fields should be NULL. */
698 
699 /*****************************************************************************/
700 
701 /*  Access to pixels
702 
703     Of course, you could also use the prn interface to obtain pixel values.
704     This, however, requires information on how eprn interprets 'gx_color_index'
705     values (see eprnrend.c for a description) and bypasses all processing steps
706     (error diffusion and the clipping of null bytes) which happen in
707     eprn_get_planes().
708 */
709 
710 /*  Number of bits and hence bit planes used to represent 'levels' intensity
711     levels in eprn_get_planes(). The return values are independent of the
712     device's state. */
713 extern unsigned int eprn_bits_for_levels(unsigned int levels);
714 
715 /*  Total number of bit planes written by eprn_get_planes().
716     The value returned is reliable only after the eprn part of the device has
717     been successfully opened. The value remains constant while the device is
718     open and equals the sum of eprn_bits_for_levels() for all colorants. */
719 extern unsigned int eprn_number_of_bitplanes(eprn_Device *dev);
720 
721 /*  Maximal lengths, in terms of the number of 'eprn_Octet' instances, for each
722     bit plane returned by eprn_get_planes() for this device.
723     These values are reliable after the eprn part of the device has been
724     successfully opened and remain constant while the device is open.
725     The array 'lengths' must have at least the length returned by
726     eprn_number_of_bitplanes(). */
727 extern void eprn_number_of_octets(eprn_Device *dev, unsigned int lengths[]);
728 
729 /*  The following function may be called only from the page printing procedure
730     (see the macro eprn_device_initdata() above). For every invocation of that
731     procedure, the first call of this function returns the scan line with
732     device coordinate y = 0, subsequent invocations return the lines with the
733     y coordinate incremented by 1 for every call.
734 
735     This function returns each scan line split into bit planes and stored into
736     the areas pointed to by the 'bitplanes' array. The order of colorants is
737     (K)(CMY) or RGB, where the parentheses indicate optional groups, depending
738     on the colour model. Within each colorant, bit planes are stored from least
739     to most significant. The number of bit planes per colorant is given by
740     eprn_bits_for_levels(levels) where 'levels' is the number of intensity
741     levels for this colorant.
742 
743     If the bit planes for a particular colorant result in the value zero for a
744     certain pixel, this indicates a complete absence of that colorant for this
745     pixel. The highest possible value is one less than the number of intensity
746     levels for that colorant.
747 
748     The 'str' entries in the 'bitplanes' array must be non-NULL and point to
749     storage areas of a length sufficient to hold the number of octets as
750     returned by eprn_number_of_octets(). The 'length' entries will be set such
751     that there will be no trailing zero octets in the octet strings returned.
752     Bits are stored in an octet from most to least signicant bit (left to
753     right). If a bit plane does not fill an integral number of octets the last
754     octet will be filled on the right as if there were additional white pixels.
755 
756     This function returns zero if there was a scan line to be fetched and a
757     non-zero value otherwise.
758  */
759 extern int eprn_get_planes(eprn_Device *dev, eprn_OctetString bitplanes[]);
760 
761 /*****************************************************************************/
762 
763 /* Auxiliary types and functions for parameter processing */
764 
765 /* Type to describe an association between a string and an integer */
766 typedef struct {
767   const char *name;
768   int value;
769 } eprn_StringAndInt;
770 
771 /*  Routines on 'eprn_StringAndInt' arrays
772     These are used to map names to integers and vice versa. It is possible to
773     have several names for the same value. The first name given in the array
774     for a particular 'value' is the canonical name for this value, i.e. the one
775     returned by the eprn_get_string() routine.
776     The arrays must be terminated by entries with a NULL pointer for 'name'.
777 */
778 struct gs_param_string_s;	/* Forward declaration */
779 extern int eprn_get_string(int in_value, const eprn_StringAndInt *table,
780   struct gs_param_string_s *out_value);
781 extern int eprn_get_int(const struct gs_param_string_s *in_value,
782   const eprn_StringAndInt *table, int *out_value);
783 
784 /*****************************************************************************/
785 
786 /* CUPS message prefixes */
787 #define CUPS_ERRPREF	"ERROR: "
788 #define CUPS_WARNPREF	"WARNING: "
789 
790 /*****************************************************************************/
791 
792 /* Selection character for tracing */
793 #ifndef EPRN_TRACE_CHAR
794 #define EPRN_TRACE_CHAR	'_'
795 #endif	/* !EPRN_TRACE_CHAR */
796 
797 /* Debugging function */
798 struct gs_param_list_s;
799 extern void eprn_dump_parameter_list(struct gs_param_list_s *plist);
800 
801 /* Internal data structures */
802 extern const eprn_StringAndInt eprn_colour_model_list[];
803 
804 /* Internal functions */
805 extern int eprn_set_page_layout(eprn_Device *dev);
806 extern int eprn_check_colour_info(const eprn_ColourInfo *list,
807   eprn_ColourModel *model, float *hres, float *vres,
808   unsigned int *black_levels, unsigned int *non_black_levels);
809 extern int eprn_fetch_scan_line(eprn_Device *dev, eprn_OctetString *line);
810 extern void eprn_finalize(bool is_RGB, unsigned int non_black_levels,
811   int planes, eprn_OctetString *plane, eprn_Octet **ptr, int pixels);
812 extern void eprn_split_FS(eprn_OctetString *line, eprn_OctetString *next_line,
813   int max_octets, eprn_ColourModel colour_model, unsigned int black_levels,
814   unsigned int non_black_levels, eprn_OctetString bitplanes[]);
815 
816 /*****************************************************************************/
817 
818 #endif	/* Inclusion protection */
819