1/*
2 * "$Id: print-pcl.c,v 1.160 2010/12/05 21:38:15 rlk Exp $"
3 *
4 *   Print plug-in HP PCL driver for the GIMP.
5 *
6 *   Copyright 1997-2000 Michael Sweet (mike@easysw.com),
7 *	Robert Krawitz (rlk@alum.mit.edu) and
8 *      Dave Hill (dave@minnie.demon.co.uk)
9 *
10 *   This program is free software; you can redistribute it and/or modify it
11 *   under the terms of the GNU General Public License as published by the Free
12 *   Software Foundation; either version 2 of the License, or (at your option)
13 *   any later version.
14 *
15 *   This program is distributed in the hope that it will be useful, but
16 *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18 *   for more details.
19 *
20 *   You should have received a copy of the GNU General Public License
21 *   along with this program; if not, write to the Free Software
22 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 */
24
25/*
26 * This file must include only standard C header files.  The core code must
27 * compile on generic platforms that don't support glib, gimp, gtk, etc.
28 */
29
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33#include <gutenprint/gutenprint.h>
34#include <gutenprint/gutenprint-intl-internal.h>
35#include "gutenprint-internal.h"
36#include <stdio.h>
37#include <string.h>
38
39/* #define DEBUG */
40/* #define PCL_DEBUG_DISABLE_BLANKLINE_REMOVAL */
41
42/*
43 * Local functions...
44 */
45static void	pcl_mode0(stp_vars_t *, unsigned char *, int, int);
46static void	pcl_mode2(stp_vars_t *, unsigned char *, int, int);
47
48#ifndef MAX
49#  define MAX(a, b) ((a) > (b) ? (a) : (b))
50#endif /* !MAX */
51
52typedef struct
53{
54  int do_blank;
55  int blank_lines;
56  unsigned char *comp_buf;
57  void (*writefunc)(stp_vars_t *, unsigned char *, int, int);	/* PCL output function */
58  int do_cret;
59  int do_cretb;
60  int do_6color;
61  int height;
62  int duplex;
63  int tumble;
64  int use_crd;
65} pcl_privdata_t;
66
67/*
68 * Generic define for a name/value set
69 */
70
71typedef struct
72{
73  const char	*pcl_name;
74  const char	*pcl_text;
75  int		pcl_code;
76  int		p0;
77  int		p1;
78} pcl_t;
79
80static const stp_dotsize_t single_dotsize[] =
81{
82  { 0x1, 1.0 }
83};
84
85static const stp_shade_t photo_dither_shades[] =
86{
87  { 1.0000, 1, single_dotsize },
88  { 0.3333, 1, single_dotsize },
89};
90
91/*
92 * Media size to PCL media size code table
93 *
94 * Note, you can force the list of papersizes given in the GUI to be only those
95 * supported by defining PCL_NO_CUSTOM_PAPERSIZES
96 */
97
98/* #define PCL_NO_CUSTOM_PAPERSIZES */
99
100#define PCL_PAPERSIZE_EXECUTIVE		1
101#define PCL_PAPERSIZE_LETTER		2
102#define PCL_PAPERSIZE_LEGAL		3
103#define PCL_PAPERSIZE_TABLOID		6	/* "Ledger" */
104#define PCL_PAPERSIZE_STATEMENT		15	/* Called "Manual" in print-util */
105#define PCL_PAPERSIZE_SUPER_B		16	/* Called "13x19" in print-util */
106#define PCL_PAPERSIZE_A5		25
107#define PCL_PAPERSIZE_A4		26
108#define PCL_PAPERSIZE_A3		27
109#define PCL_PAPERSIZE_JIS_B5		45
110#define PCL_PAPERSIZE_JIS_B4		46
111#define PCL_PAPERSIZE_HAGAKI_CARD	71
112#define PCL_PAPERSIZE_OUFUKU_CARD	72
113#define PCL_PAPERSIZE_A6_CARD		73
114#define PCL_PAPERSIZE_4x6		74
115#define PCL_PAPERSIZE_5x8		75
116#define PCL_PAPERSIZE_3x5		78
117#define PCL_PAPERSIZE_MONARCH_ENV	80
118#define PCL_PAPERSIZE_COMMERCIAL10_ENV	81
119#define PCL_PAPERSIZE_DL_ENV		90
120#define PCL_PAPERSIZE_C5_ENV		91
121#define PCL_PAPERSIZE_C6_ENV		92
122#define PCL_PAPERSIZE_CUSTOM		101	/* Custom size */
123#define PCL_PAPERSIZE_INVITATION_ENV	109
124#define PCL_PAPERSIZE_JAPANESE_3_ENV	110
125#define PCL_PAPERSIZE_JAPANESE_4_ENV	111
126#define PCL_PAPERSIZE_KAKU_ENV		113
127#define PCL_PAPERSIZE_HP_CARD		114	/* HP Greeting card!?? */
128
129/*
130 * This data comes from the HP documentation "Deskjet 1220C and 1120C
131 * PCL reference guide 2.0, Nov 1999". NOTE: The first name *must* match
132 * those in print-util.c for the lookups to work properly!
133 * The long names are not used so they have been removed, the ones in
134 * print-util.c are used in the interface.
135 */
136
137static const pcl_t pcl_media_sizes[] =
138{
139    { "Executive", "notused", PCL_PAPERSIZE_EXECUTIVE},			/* US Exec (7.25 x 10.5 in) */
140    { "Letter", "notused", PCL_PAPERSIZE_LETTER},			/* US Letter (8.5 x 11 in) */
141    { "Legal", "notused", PCL_PAPERSIZE_LEGAL},				/* US Legal (8.5 x 14 in) */
142    { "Tabloid", "notused", PCL_PAPERSIZE_TABLOID},			/* US Tabloid (11 x 17 in) */
143    { "Statement", "notused", PCL_PAPERSIZE_STATEMENT},			/* US Manual/Statement (5.5 x 8.5 in) */
144    { "SuperB", "notused", PCL_PAPERSIZE_SUPER_B},			/* US 13x19/Super B (13 x 19 in) */
145    { "A5", "notused", PCL_PAPERSIZE_A5},				/* ISO/JIS A5 (148 x 210 mm) */
146    { "A4", "notused", PCL_PAPERSIZE_A4},				/* ISO/JIS A4 (210 x 297 mm) */
147    { "A3", "notused", PCL_PAPERSIZE_A3},				/* ISO/JIS A3 (297 x 420 mm) */
148    { "B5", "notused", PCL_PAPERSIZE_JIS_B5},				/* JIS B5 (182 x 257 mm). */
149    { "B4", "notused", PCL_PAPERSIZE_JIS_B4},				/* JIS B4 (257 x 364 mm). */
150    { "w283h420", "notused", PCL_PAPERSIZE_HAGAKI_CARD},		/* Japanese Hagaki Card (100 x 148 mm) */
151    { "w420h567", "notused", PCL_PAPERSIZE_OUFUKU_CARD},		/* Japanese Oufuku Card (148 x 200 mm) */
152    { "A6", "notused", PCL_PAPERSIZE_A6_CARD},				/* ISO/JIS A6 card */
153    { "w288h432", "notused", PCL_PAPERSIZE_4x6},			/* US Index card (4 x 6 in) */
154    { "w360h576", "notused", PCL_PAPERSIZE_5x8},			/* US Index card (5 x 8 in) */
155    { "w216h360", "notused", PCL_PAPERSIZE_3x5},			/* US Index card (3 x 5 in) */
156    { "Monarch", "notused", PCL_PAPERSIZE_MONARCH_ENV},			/* Monarch Envelope (3 7/8 x 7 1/2 in) */
157    { "COM10", "notused", PCL_PAPERSIZE_COMMERCIAL10_ENV},		/* US Commercial 10 Envelope (4.125 x 9.5 in) Portrait */
158    { "DL", "notused", PCL_PAPERSIZE_DL_ENV},				/* DL envelope (110 x 220 mm) Portrait */
159    { "C5", "notused", PCL_PAPERSIZE_C5_ENV},				/* C5 envelope (162 x 229 mm) */
160    { "C6", "notused", PCL_PAPERSIZE_C6_ENV},				/* C6 envelope (114 x 162 mm) */
161    { "w315h414", "notused", PCL_PAPERSIZE_INVITATION_ENV},		/* US A2 Invitation envelope (4 3/8 x 5 3/4 in) */
162    { "w340h666", "notused", PCL_PAPERSIZE_JAPANESE_3_ENV},		/* Japanese Long Envelope #3 (120 x 235 mm) */
163    { "w255h581", "notused", PCL_PAPERSIZE_JAPANESE_4_ENV},		/* Japanese Long Envelope #4 (90 x 205 mm) */
164    { "w680h941", "notused", PCL_PAPERSIZE_KAKU_ENV},			/* Japanese Kaku Envelope (240 x 332.1 mm) */
165/**** MRS: this size not supported by print-util funcs! ****/
166    { "w612h792", "notused", PCL_PAPERSIZE_HP_CARD}, 			/* Hp greeting card */
167};
168#define NUM_PRINTER_PAPER_SIZES	(sizeof(pcl_media_sizes) / sizeof(pcl_t))
169
170/*
171 * Media type to code table
172 */
173
174#define PCL_PAPERTYPE_PLAIN	0
175#define PCL_PAPERTYPE_BOND	1
176#define PCL_PAPERTYPE_PREMIUM	2
177#define PCL_PAPERTYPE_GLOSSY	3	/* or photo */
178#define PCL_PAPERTYPE_TRANS	4
179#define PCL_PAPERTYPE_QPHOTO	5	/* Quick dry photo (2000 only) */
180#define PCL_PAPERTYPE_QTRANS	6	/* Quick dry transparency (2000 only) */
181
182static const pcl_t pcl_media_types[] =
183{
184    { "Plain", N_ ("Plain"), PCL_PAPERTYPE_PLAIN},
185    { "Bond", N_ ("Bond"), PCL_PAPERTYPE_BOND},
186    { "Premium", N_ ("Premium"), PCL_PAPERTYPE_PREMIUM},
187    { "Glossy", N_ ("Glossy Photo"), PCL_PAPERTYPE_GLOSSY},
188    { "Transparency", N_ ("Transparency"), PCL_PAPERTYPE_TRANS},
189    { "GlossyQD", N_ ("Quick-dry Photo"), PCL_PAPERTYPE_QPHOTO},
190    { "TransparencyQD", N_ ("Quick-dry Transparency"), PCL_PAPERTYPE_QTRANS},
191};
192#define NUM_PRINTER_PAPER_TYPES	(sizeof(pcl_media_types) / sizeof(pcl_t))
193
194/*
195 * Media feed to code table. There are different names for the same code,
196 * so we encode them by adding "lumps" of "PAPERSOURCE_MOD".
197 * This is removed later to get back to the main codes.
198 */
199
200#define PAPERSOURCE_MOD			16
201#define PAPERSOURCE_340_MOD		(PAPERSOURCE_MOD)
202#define PAPERSOURCE_DJ_MOD		(PAPERSOURCE_MOD << 1)
203#define PAPERSOURCE_ADJ_GUIDE		(PAPERSOURCE_MOD << 2)
204
205#define PCL_PAPERSOURCE_STANDARD	0	/* Don't output code */
206#define PCL_PAPERSOURCE_MANUAL		2
207#define PCL_PAPERSOURCE_MANUAL_ADJ	(PCL_PAPERSOURCE_MANUAL + PAPERSOURCE_ADJ_GUIDE)
208#define PCL_PAPERSOURCE_ENVELOPE	3	/* Not used */
209
210/* LaserJet types */
211#define PCL_PAPERSOURCE_LJ_TRAY2	1
212#define PCL_PAPERSOURCE_LJ_TRAY3	4
213#define PCL_PAPERSOURCE_LJ_TRAY4	5
214#define PCL_PAPERSOURCE_LJ_TRAY1	8
215#define PCL_PAPERSOURCE_LJ_TRAY1_ADJ	(PCL_PAPERSOURCE_LJ_TRAY1 + PAPERSOURCE_ADJ_GUIDE)
216#define PCL_PAPERSOURCE_LJ_TRAY2_ADJ	(PCL_PAPERSOURCE_LJ_TRAY2 + PAPERSOURCE_ADJ_GUIDE)
217#define PCL_PAPERSOURCE_LJ_TRAY3_ADJ	(PCL_PAPERSOURCE_LJ_TRAY3 + PAPERSOURCE_ADJ_GUIDE)
218#define PCL_PAPERSOURCE_LJ_TRAY4_ADJ	(PCL_PAPERSOURCE_LJ_TRAY4 + PAPERSOURCE_ADJ_GUIDE)
219
220/* Deskjet 340 types */
221#define PCL_PAPERSOURCE_340_PCSF	(1 + PAPERSOURCE_340_MOD)
222						/* Portable sheet feeder for 340 */
223#define PCL_PAPERSOURCE_340_DCSF	(4 + PAPERSOURCE_340_MOD)
224						/* Desktop sheet feeder for 340 */
225
226/* Other Deskjet types */
227#define PCL_PAPERSOURCE_DJ_TRAY		(1 + PAPERSOURCE_DJ_MOD)
228#define PCL_PAPERSOURCE_DJ_TRAY2	(4 + PAPERSOURCE_DJ_MOD)
229						/* Tray 2 for 2500 */
230#define PCL_PAPERSOURCE_DJ_OPTIONAL	(5 + PAPERSOURCE_DJ_MOD)
231						/* Optional source for 2500 */
232#define PCL_PAPERSOURCE_DJ_AUTO		(7 + PAPERSOURCE_DJ_MOD)
233						/* Autoselect for 2500 */
234
235static const pcl_t pcl_media_sources[] =
236{
237    { "Standard", N_ ("Standard"), PCL_PAPERSOURCE_STANDARD},
238    { "Manual", N_ ("Manual"), PCL_PAPERSOURCE_MANUAL},
239    { "ManualAdj", N_ ("Manual - Movable Guides"), PCL_PAPERSOURCE_MANUAL_ADJ},
240/*  {"Envelope", PCL_PAPERSOURCE_ENVELOPE}, */
241    { "MultiPurposeAdj", N_ ("Tray 1 - Movable Guides"), PCL_PAPERSOURCE_LJ_TRAY1_ADJ},
242    { "MultiPurpose", N_ ("Tray 1"), PCL_PAPERSOURCE_LJ_TRAY1},
243    { "UpperAdj", N_ ("Tray 2 - Movable Guides"), PCL_PAPERSOURCE_LJ_TRAY2_ADJ},
244    { "Upper", N_ ("Tray 2"), PCL_PAPERSOURCE_LJ_TRAY2},
245    { "LowerAdj", N_ ("Tray 3 - Movable Guides"), PCL_PAPERSOURCE_LJ_TRAY3_ADJ},
246    { "Lower", N_ ("Tray 3"), PCL_PAPERSOURCE_LJ_TRAY3},
247    { "LargeCapacityAdj", N_ ("Tray 4 - Movable Guides"), PCL_PAPERSOURCE_LJ_TRAY4_ADJ},
248    { "LargeCapacity", N_ ("Tray 4"), PCL_PAPERSOURCE_LJ_TRAY4},
249    { "Portable", N_ ("Portable Sheet Feeder"), PCL_PAPERSOURCE_340_PCSF},
250    { "Desktop", N_ ("Desktop Sheet Feeder"), PCL_PAPERSOURCE_340_DCSF},
251    { "Tray", N_ ("Tray"), PCL_PAPERSOURCE_DJ_TRAY},
252    { "Tray2", N_ ("Tray 2"), PCL_PAPERSOURCE_DJ_TRAY2},
253    { "Optional", N_ ("Optional Source"), PCL_PAPERSOURCE_DJ_OPTIONAL},
254    { "Auto", N_ ("Autoselect"), PCL_PAPERSOURCE_DJ_AUTO},
255};
256#define NUM_PRINTER_PAPER_SOURCES	(sizeof(pcl_media_sources) / sizeof(pcl_t))
257
258#define PCL_RES_150_150		1
259#define PCL_RES_300_300		2
260#define PCL_RES_600_300		4	/* DJ 600 series */
261#define PCL_RES_600_600_MONO	8	/* DJ 600/800/1100/2000 b/w only */
262#define PCL_RES_600_600		16	/* DJ 9xx/1220C/PhotoSmart */
263#define PCL_RES_1200_600	32	/* DJ 9xx/1220C/PhotoSmart */
264#define PCL_RES_2400_600	64	/* DJ 9xx/1220C/PhotoSmart */
265
266static const pcl_t pcl_resolutions[] =
267{
268    { "150dpi", N_("150x150 DPI"), PCL_RES_150_150, 150, 150},
269    { "300dpi", N_("300x300 DPI"), PCL_RES_300_300, 300, 300},
270    { "600x300dpi", N_("600x300 DPI"), PCL_RES_600_300, 600, 300},
271    { "600mono", N_("600x600 DPI monochrome"), PCL_RES_600_600_MONO, 600, 600},
272    { "600dpi", N_("600x600 DPI"), PCL_RES_600_600, 600, 600},
273    { "1200x600dpi", N_("1200x600 DPI"), PCL_RES_1200_600, 1200, 600},
274    { "2400x600dpi", N_("2400x600 DPI"), PCL_RES_2400_600, 2400, 600},
275};
276#define NUM_RESOLUTIONS		(sizeof(pcl_resolutions) / sizeof (pcl_t))
277
278static const pcl_t pcl_qualities[] =
279{
280    { "Draft", N_("Draft"), PCL_RES_150_150, 150, 150},
281    { "Standard", N_("Standard"), PCL_RES_300_300, 300, 300},
282    { "High", N_("High"), PCL_RES_600_600, 600, 600},
283    { "High", N_("Standard"), PCL_RES_600_300, 600, 300},
284    { "Photo", N_("Photo"), PCL_RES_1200_600, 1200, 600},
285    { "Photo", N_("Photo"), PCL_RES_2400_600, 2400, 600},
286};
287#define NUM_QUALITIES		(sizeof(pcl_qualities) / sizeof (pcl_t))
288
289typedef struct {
290  int top_margin;
291  int bottom_margin;
292  int left_margin;
293  int right_margin;
294} margins_t;
295
296/*
297 * Printer capability data
298 */
299
300typedef struct {
301  int model;
302  int custom_max_width;
303  int custom_max_height;
304  int custom_min_width;
305  int custom_min_height;
306  int resolutions;
307  margins_t normal_margins;
308  margins_t a4_margins;
309  int color_type;		/* 2 print head or one, 2 level or 4 */
310  int stp_printer_type;		/* Deskjet/Laserjet and quirks */
311/* The paper size, paper type and paper source codes cannot be combined */
312  const short *paper_sizes;	/* Paper sizes */
313  const short *paper_types;	/* Paper types */
314  const short *paper_sources;	/* Paper sources */
315  } pcl_cap_t;
316
317#define PCL_COLOR_NONE		0
318#define PCL_COLOR_CMY		1	/* One print head */
319#define PCL_COLOR_CMYK		2	/* Two print heads */
320#define PCL_COLOR_CMYK4		4	/* CRet printing */
321#define PCL_COLOR_CMYKcm	8	/* CMY + Photo Cart */
322#define PCL_COLOR_CMYK4b	16	/* CRet for HP840c */
323
324#define PCL_PRINTER_LJ		1
325#define PCL_PRINTER_DJ		2
326#define PCL_PRINTER_NEW_ERG	4	/* use "\033*rC" to end raster graphics,
327					   instead of "\033*rB" */
328#define PCL_PRINTER_TIFF	8	/* Use TIFF compression */
329#define PCL_PRINTER_MEDIATYPE	16	/* Use media type & print quality */
330#define PCL_PRINTER_CUSTOM_SIZE	32	/* Custom sizes supported */
331#define PCL_PRINTER_BLANKLINE	64	/* Blank line removal supported */
332#define PCL_PRINTER_DUPLEX	128	/* Printer can have duplexer */
333
334/*
335 * FIXME - the 520 shouldn't be lumped in with the 500 as it supports
336 * more paper sizes.
337 *
338 * The following models use depletion, raster quality and shingling:-
339 * 500, 500c, 510, 520, 550c, 560c.
340 * The rest use Media Type and Print Quality.
341 *
342 * This data comes from the HP documentation "Deskjet 1220C and 1120C
343 * PCL reference guide 2.0, Nov 1999".
344 */
345
346static const short emptylist[] =
347{
348  -1
349};
350
351static const short standard_papersizes[] =
352{
353  PCL_PAPERSIZE_EXECUTIVE,
354  PCL_PAPERSIZE_STATEMENT,
355  PCL_PAPERSIZE_LETTER,
356  PCL_PAPERSIZE_LEGAL,
357  PCL_PAPERSIZE_A4,
358  -1,
359};
360
361static const short letter_only_papersizes[] =
362{
363  PCL_PAPERSIZE_LETTER,
364  -1
365};
366
367static const short letter_a4_papersizes[] =
368{
369  PCL_PAPERSIZE_A4,
370  PCL_PAPERSIZE_LETTER,
371  -1
372};
373
374static const short dj340_papersizes[] =
375{
376  PCL_PAPERSIZE_EXECUTIVE,
377  PCL_PAPERSIZE_LETTER,
378  PCL_PAPERSIZE_LEGAL,
379  PCL_PAPERSIZE_A4,
380  -1,
381};
382
383static const short dj400_papersizes[] =
384{
385  PCL_PAPERSIZE_EXECUTIVE,
386  PCL_PAPERSIZE_LETTER,
387  PCL_PAPERSIZE_LEGAL,
388  PCL_PAPERSIZE_A4,
389  PCL_PAPERSIZE_JIS_B5,
390  -1,
391};
392
393static const short dj500_papersizes[] =
394{
395/*    PCL_PAPERSIZE_EXECUTIVE, The 500 doesn't support this, the 520 does */
396  PCL_PAPERSIZE_LETTER,
397  PCL_PAPERSIZE_LEGAL,
398  PCL_PAPERSIZE_A4,
399  PCL_PAPERSIZE_COMMERCIAL10_ENV,
400/*    PCL_PAPERSIZE_DL_ENV,    The 500 doesn't support this, the 520 does */
401  -1,
402};
403
404static const short dj540_papersizes[] =
405{
406  PCL_PAPERSIZE_EXECUTIVE,
407  PCL_PAPERSIZE_LETTER,
408  PCL_PAPERSIZE_LEGAL,
409  PCL_PAPERSIZE_A4,
410  PCL_PAPERSIZE_A5,
411  PCL_PAPERSIZE_JIS_B5,
412  PCL_PAPERSIZE_HAGAKI_CARD,
413  PCL_PAPERSIZE_A6_CARD,
414  PCL_PAPERSIZE_4x6,
415  PCL_PAPERSIZE_5x8,
416  PCL_PAPERSIZE_COMMERCIAL10_ENV,
417  PCL_PAPERSIZE_DL_ENV,
418  PCL_PAPERSIZE_C6_ENV,
419  -1,
420};
421
422static const short dj600_papersizes[] =
423{
424  PCL_PAPERSIZE_EXECUTIVE,
425  PCL_PAPERSIZE_LETTER,
426  PCL_PAPERSIZE_LEGAL,
427  PCL_PAPERSIZE_A4,
428  PCL_PAPERSIZE_A5,
429  PCL_PAPERSIZE_HAGAKI_CARD,
430  PCL_PAPERSIZE_A6_CARD,
431  PCL_PAPERSIZE_4x6,
432  PCL_PAPERSIZE_5x8,
433  PCL_PAPERSIZE_COMMERCIAL10_ENV,
434  PCL_PAPERSIZE_DL_ENV,
435  PCL_PAPERSIZE_C6_ENV,
436  PCL_PAPERSIZE_INVITATION_ENV,
437  -1,
438};
439
440static const short dj1220_papersizes[] =
441{
442  PCL_PAPERSIZE_EXECUTIVE,
443  PCL_PAPERSIZE_LETTER,
444  PCL_PAPERSIZE_LEGAL,
445  PCL_PAPERSIZE_TABLOID,
446  PCL_PAPERSIZE_STATEMENT,
447  PCL_PAPERSIZE_SUPER_B,
448  PCL_PAPERSIZE_A5,
449  PCL_PAPERSIZE_A4,
450  PCL_PAPERSIZE_A3,
451  PCL_PAPERSIZE_JIS_B5,
452  PCL_PAPERSIZE_JIS_B4,
453  PCL_PAPERSIZE_HAGAKI_CARD,
454  PCL_PAPERSIZE_OUFUKU_CARD,
455  PCL_PAPERSIZE_A6_CARD,
456  PCL_PAPERSIZE_4x6,
457  PCL_PAPERSIZE_5x8,
458  PCL_PAPERSIZE_3x5,
459  PCL_PAPERSIZE_HP_CARD,
460  PCL_PAPERSIZE_MONARCH_ENV,
461  PCL_PAPERSIZE_COMMERCIAL10_ENV,
462  PCL_PAPERSIZE_DL_ENV,
463  PCL_PAPERSIZE_C5_ENV,
464  PCL_PAPERSIZE_C6_ENV,
465  PCL_PAPERSIZE_INVITATION_ENV,
466  PCL_PAPERSIZE_JAPANESE_3_ENV,
467  PCL_PAPERSIZE_JAPANESE_4_ENV,
468  PCL_PAPERSIZE_KAKU_ENV,
469  -1,
470};
471
472static const short dj1100_papersizes[] =
473{
474  PCL_PAPERSIZE_EXECUTIVE,
475  PCL_PAPERSIZE_LETTER,
476  PCL_PAPERSIZE_LEGAL,
477  PCL_PAPERSIZE_TABLOID,
478  PCL_PAPERSIZE_STATEMENT,
479  PCL_PAPERSIZE_SUPER_B,
480  PCL_PAPERSIZE_A5,
481  PCL_PAPERSIZE_A4,
482  PCL_PAPERSIZE_A3,
483  PCL_PAPERSIZE_JIS_B5,
484  PCL_PAPERSIZE_JIS_B4,
485  PCL_PAPERSIZE_HAGAKI_CARD,
486  PCL_PAPERSIZE_A6_CARD,
487  PCL_PAPERSIZE_4x6,
488  PCL_PAPERSIZE_5x8,
489  PCL_PAPERSIZE_COMMERCIAL10_ENV,
490  PCL_PAPERSIZE_DL_ENV,
491  PCL_PAPERSIZE_C6_ENV,
492  PCL_PAPERSIZE_INVITATION_ENV,
493  PCL_PAPERSIZE_JAPANESE_3_ENV,
494  PCL_PAPERSIZE_JAPANESE_4_ENV,
495  PCL_PAPERSIZE_KAKU_ENV,
496  -1,
497};
498
499static const short dj1200_papersizes[] =
500{
501  /* This printer is not mentioned in the Comparison tables,
502     so I'll just pick some likely sizes... */
503  PCL_PAPERSIZE_EXECUTIVE,
504  PCL_PAPERSIZE_LETTER,
505  PCL_PAPERSIZE_LEGAL,
506  PCL_PAPERSIZE_A5,
507  PCL_PAPERSIZE_A4,
508  PCL_PAPERSIZE_4x6,
509  PCL_PAPERSIZE_5x8,
510  -1,
511};
512
513static const short dj2000_papersizes[] =
514{
515  PCL_PAPERSIZE_EXECUTIVE,
516  PCL_PAPERSIZE_LETTER,
517  PCL_PAPERSIZE_LEGAL,
518  PCL_PAPERSIZE_A5,
519  PCL_PAPERSIZE_A4,
520  PCL_PAPERSIZE_HAGAKI_CARD,
521  PCL_PAPERSIZE_A6_CARD,
522  PCL_PAPERSIZE_4x6,
523  PCL_PAPERSIZE_5x8,
524  PCL_PAPERSIZE_3x5,
525  PCL_PAPERSIZE_COMMERCIAL10_ENV,
526  PCL_PAPERSIZE_DL_ENV,
527  PCL_PAPERSIZE_C6_ENV,
528  PCL_PAPERSIZE_INVITATION_ENV,
529  -1,
530};
531
532static const short dj2500_papersizes[] =
533{
534  PCL_PAPERSIZE_EXECUTIVE,
535  PCL_PAPERSIZE_LETTER,
536  PCL_PAPERSIZE_LEGAL,
537  PCL_PAPERSIZE_TABLOID,
538  PCL_PAPERSIZE_STATEMENT,
539  PCL_PAPERSIZE_A5,
540  PCL_PAPERSIZE_A4,
541  PCL_PAPERSIZE_A3,
542  PCL_PAPERSIZE_JIS_B5,
543  PCL_PAPERSIZE_JIS_B4,
544  PCL_PAPERSIZE_HAGAKI_CARD,
545  PCL_PAPERSIZE_A6_CARD,
546  PCL_PAPERSIZE_4x6,
547  PCL_PAPERSIZE_5x8,
548  PCL_PAPERSIZE_COMMERCIAL10_ENV,
549  PCL_PAPERSIZE_DL_ENV,
550  -1,
551};
552
553static const short ljsmall_papersizes[] =
554{
555  PCL_PAPERSIZE_EXECUTIVE,
556  PCL_PAPERSIZE_STATEMENT,
557  PCL_PAPERSIZE_LETTER,
558  PCL_PAPERSIZE_LEGAL,
559  PCL_PAPERSIZE_A4,
560  PCL_PAPERSIZE_MONARCH_ENV,
561  PCL_PAPERSIZE_COMMERCIAL10_ENV,
562  PCL_PAPERSIZE_DL_ENV,
563  PCL_PAPERSIZE_C5_ENV,
564  PCL_PAPERSIZE_C6_ENV,
565  -1,
566};
567
568static const short ljbig_papersizes[] =
569{
570  PCL_PAPERSIZE_EXECUTIVE,
571  PCL_PAPERSIZE_STATEMENT,
572  PCL_PAPERSIZE_LETTER,
573  PCL_PAPERSIZE_LEGAL,
574  PCL_PAPERSIZE_TABLOID,
575  PCL_PAPERSIZE_SUPER_B,
576  PCL_PAPERSIZE_A5,
577  PCL_PAPERSIZE_A4,
578  PCL_PAPERSIZE_A3,
579  PCL_PAPERSIZE_JIS_B5,
580  PCL_PAPERSIZE_JIS_B4,                /* Guess */
581  PCL_PAPERSIZE_4x6,
582  PCL_PAPERSIZE_5x8,
583  PCL_PAPERSIZE_MONARCH_ENV,
584  PCL_PAPERSIZE_COMMERCIAL10_ENV,
585  PCL_PAPERSIZE_DL_ENV,
586  PCL_PAPERSIZE_C5_ENV,
587  PCL_PAPERSIZE_C6_ENV,
588  -1,
589};
590
591static const short ljtabloid_papersizes[] =
592{
593  PCL_PAPERSIZE_EXECUTIVE,
594  PCL_PAPERSIZE_STATEMENT,
595  PCL_PAPERSIZE_LETTER,
596  PCL_PAPERSIZE_LEGAL,
597  PCL_PAPERSIZE_TABLOID,
598  PCL_PAPERSIZE_A5,
599  PCL_PAPERSIZE_A4,
600  PCL_PAPERSIZE_A3,
601  PCL_PAPERSIZE_JIS_B5,
602  PCL_PAPERSIZE_JIS_B4,                /* Guess */
603  PCL_PAPERSIZE_4x6,
604  PCL_PAPERSIZE_5x8,
605  PCL_PAPERSIZE_MONARCH_ENV,
606  PCL_PAPERSIZE_COMMERCIAL10_ENV,
607  PCL_PAPERSIZE_DL_ENV,
608  PCL_PAPERSIZE_C5_ENV,
609  PCL_PAPERSIZE_C6_ENV,
610  -1,
611};
612
613static const short basic_papertypes[] =
614{
615  PCL_PAPERTYPE_PLAIN,
616  PCL_PAPERTYPE_BOND,
617  PCL_PAPERTYPE_PREMIUM,
618  PCL_PAPERTYPE_GLOSSY,
619  PCL_PAPERTYPE_TRANS,
620  -1,
621};
622
623static const short new_papertypes[] =
624{
625  PCL_PAPERTYPE_PLAIN,
626  PCL_PAPERTYPE_BOND,
627  PCL_PAPERTYPE_PREMIUM,
628  PCL_PAPERTYPE_GLOSSY,
629  PCL_PAPERTYPE_TRANS,
630  PCL_PAPERTYPE_QPHOTO,
631  PCL_PAPERTYPE_QTRANS,
632  -1,
633};
634
635static const short laserjet_papersources[] =
636{
637  PCL_PAPERSOURCE_STANDARD,
638  PCL_PAPERSOURCE_MANUAL_ADJ,
639  PCL_PAPERSOURCE_MANUAL,
640  PCL_PAPERSOURCE_LJ_TRAY1_ADJ,
641  PCL_PAPERSOURCE_LJ_TRAY1,
642  PCL_PAPERSOURCE_LJ_TRAY2_ADJ,
643  PCL_PAPERSOURCE_LJ_TRAY2,
644  PCL_PAPERSOURCE_LJ_TRAY3_ADJ,
645  PCL_PAPERSOURCE_LJ_TRAY3,
646  PCL_PAPERSOURCE_LJ_TRAY4_ADJ,
647  PCL_PAPERSOURCE_LJ_TRAY4,
648  -1,
649};
650
651static const short dj340_papersources[] =
652{
653  PCL_PAPERSOURCE_STANDARD,
654  PCL_PAPERSOURCE_MANUAL,
655  PCL_PAPERSOURCE_340_PCSF,
656  PCL_PAPERSOURCE_340_DCSF,
657  -1,
658};
659
660static const short dj_papersources[] =
661{
662  PCL_PAPERSOURCE_STANDARD,
663  PCL_PAPERSOURCE_MANUAL,
664  PCL_PAPERSOURCE_DJ_TRAY,
665  -1,
666};
667
668static const short dj2500_papersources[] =
669{
670  PCL_PAPERSOURCE_STANDARD,
671  PCL_PAPERSOURCE_MANUAL,
672  PCL_PAPERSOURCE_DJ_AUTO,
673  PCL_PAPERSOURCE_DJ_TRAY,
674  PCL_PAPERSOURCE_DJ_TRAY2,
675  PCL_PAPERSOURCE_DJ_OPTIONAL,
676  -1,
677};
678
679static const short standard_papersources[] =
680{
681  PCL_PAPERSOURCE_STANDARD,
682  -1
683};
684
685static const pcl_cap_t pcl_model_capabilities[] =
686{
687  /* Default/unknown printer - assume laserjet */
688  { 0,
689    17 * 72 / 2, 14 * 72,		/* Max paper size */
690    1, 1,				/* Min paper size */
691    PCL_RES_150_150 | PCL_RES_300_300,	/* Resolutions */
692    {12, 12, 18, 18},			/* non-A4 Margins */
693    {12, 12, 10, 10},			/* A4 Margins */
694    PCL_COLOR_NONE,
695    PCL_PRINTER_LJ,
696    standard_papersizes,
697    emptylist,
698    emptylist,
699  },
700  /* DesignJet 230/430 (monochrome ) */
701  { 10230,
702    36 * 72, 150 * 12 * 72,		/* 150ft in roll mode, 64" in sheet */
703    826 * 72 / 100, 583 * 72 / 100,	/* 8.3" wide min in sheet mode */
704    PCL_RES_300_300 | PCL_RES_600_600,
705    {49, 49, 15, 15},
706    {49, 49, 15, 15},
707    PCL_COLOR_NONE,
708    PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE | PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_NEW_ERG,
709    letter_a4_papersizes,
710    basic_papertypes,
711    standard_papersources,
712  },
713  /* DesignJet 250C/450C/455CA/488CA */
714  /* The "CA" versions have a "software RIP" but are the same hardware */
715  { 10250,
716    36 * 72, 150 * 12 * 72,		/* 150ft in roll mode, 64" in sheet */
717    826 * 72 / 100, 583 * 72 / 100,	/* 8.3" wide min in sheet mode */
718    PCL_RES_300_300 | PCL_RES_600_600_MONO,
719    {49, 49, 15, 15},
720    {49, 49, 15, 15},
721    PCL_COLOR_CMYK,
722    PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE | PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_NEW_ERG,
723    letter_a4_papersizes,
724    basic_papertypes,
725    standard_papersources,
726  },
727  /* DesignJet 700 (monochrome) */
728  { 10700,
729    36 * 72, 150 * 12 * 72,		/* 150ft in roll mode, 64" in sheet */
730    826 * 72 / 100, 583 * 72 / 100,	/* 8.3" wide min in sheet mode */
731    PCL_RES_300_300 | PCL_RES_600_600,
732    {30, 30, 15, 15},		/* These margins are for sheet mode FIX */
733    {30, 30, 15, 15},
734    PCL_COLOR_NONE,
735    PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE | PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_NEW_ERG,
736    letter_a4_papersizes,
737    basic_papertypes,
738    standard_papersources,
739  },
740  /* DesignJet 750C */
741  { 10750,
742    36 * 72, 150 * 12 * 72,		/* 150ft in roll mode, 64" in sheet */
743    826 * 72 / 100, 583 * 72 / 100,	/* 8.3" wide min in sheet mode */
744    PCL_RES_300_300 | PCL_RES_600_600_MONO,
745    {30, 30, 15, 15},	/* These margins are for roll mode FIX */
746    {30, 30, 15, 15},
747    PCL_COLOR_CMYK,
748    PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE | PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_NEW_ERG,
749    letter_a4_papersizes,
750    basic_papertypes,
751    standard_papersources,
752  },
753  /* DesignJet 2000C/2500C (36" wide) */
754  { 12500,	/* Deskjet 2500 already has "2500" */
755    36 * 72, 150 * 12 * 72,		/* 150ft in roll mode, 64" in sheet */
756    826 * 72 / 100, 583 * 72 / 100,	/* 8.3" wide min in sheet mode */
757    PCL_RES_300_300 | PCL_RES_600_600_MONO,
758    {49, 49, 15, 15},		/* Check/Fix */
759    {49, 49, 15, 15},
760    PCL_COLOR_CMYK,
761    PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE | PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_NEW_ERG,
762    letter_a4_papersizes,
763    basic_papertypes,
764    standard_papersources,
765  },
766  /* DesignJet 3000C/3500C (54" wide) */
767  { 13500,	/* Deskjet 2500 already has "2500" */
768    54 * 72, 150 * 12 * 72,		/* 150ft in roll mode, 64" in sheet */
769    826 * 72 / 100, 583 * 72 / 100,	/* 8.3" wide min in sheet mode */
770    PCL_RES_300_300 | PCL_RES_600_600_MONO,
771    {49, 49, 15, 15},		/* Check/Fix */
772    {49, 49, 15, 15},
773    PCL_COLOR_CMYK,
774    PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE | PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_NEW_ERG,
775    letter_a4_papersizes,
776    basic_papertypes,
777    standard_papersources,
778  },
779  /* Deskjet 340 */
780  { 340,
781    17 * 72 / 2, 14 * 72,
782    1, 1,				/* Min paper size */
783    PCL_RES_150_150 | PCL_RES_300_300,
784    {6, 48, 18, 18},	/* from bpd07933.pdf */
785    {6, 48, 10, 11},	/* from bpd07933.pdf */
786    PCL_COLOR_CMY,
787    PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
788    dj340_papersizes,
789    basic_papertypes,
790    dj340_papersources,
791  },
792  /* Deskjet 400 */
793  { 400,
794    17 * 72 / 2, 14 * 72,
795    1, 1,				/* Min paper size */
796    PCL_RES_150_150 | PCL_RES_300_300,
797    {7, 41, 18, 18},
798    {7, 41, 10, 10},	/* Check/Fix */
799    PCL_COLOR_CMY,
800    PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
801    dj400_papersizes,
802    basic_papertypes,
803    emptylist,
804  },
805  /* Deskjet 500, 520. Lexmark 4076 */
806  { 500,
807    17 * 72 / 2, 14 * 72,
808    1, 1,				/* Min paper size */
809    PCL_RES_150_150 | PCL_RES_300_300,
810    {7, 41, 18, 18},
811    {7, 41, 10, 10},	/* Check/Fix */
812    PCL_COLOR_NONE,
813    PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
814    dj500_papersizes,
815    basic_papertypes,
816    dj_papersources,
817  },
818  /* Deskjet 500C */
819  { 501,
820    17 * 72 / 2, 14 * 72,
821    1, 1,				/* Min paper size */
822    PCL_RES_150_150 | PCL_RES_300_300,
823    {7, 33, 18, 18},
824    {7, 33, 10, 10},	/* Check/Fix */
825    PCL_COLOR_CMY,
826    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
827    dj500_papersizes,
828    basic_papertypes,
829    dj_papersources,
830  },
831  /* Deskjet 540C */
832  { 540,
833    17 * 72 / 2, 14 * 72,
834    1, 1,				/* Min paper size */
835    PCL_RES_150_150 | PCL_RES_300_300,
836    {7, 33, 18, 18},
837    {7, 33, 10, 10},	/* Check/Fix */
838    PCL_COLOR_CMY,
839    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
840      PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
841    dj540_papersizes,
842    basic_papertypes,
843    dj_papersources,
844  },
845  /* Deskjet 550C, 560C */
846  { 550,
847    17 * 72 / 2, 14 * 72,
848    1, 1,				/* Min paper size */
849    PCL_RES_150_150 | PCL_RES_300_300,
850    {3, 33, 18, 18},
851    {5, 33, 10, 10},
852    PCL_COLOR_CMYK,
853    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
854/* The 550/560 support COM10 and DL envelope, but the control codes
855   are negative, indicating landscape mode. This needs thinking about! */
856    dj340_papersizes,
857    basic_papertypes,
858    dj_papersources,
859  },
860  /* Deskjet 600/600C */
861  { 600,
862    17 * 72 / 2, 14 * 72,
863    5 * 72, 583 * 72 / 100,		/* Min paper size */
864    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_300 | PCL_RES_600_600_MONO,
865    {0, 33, 18, 18},
866    {0, 33, 10, 10},	/* Check/Fix */
867    PCL_COLOR_CMY,
868    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
869      PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
870    dj600_papersizes,
871    basic_papertypes,
872    emptylist,
873  },
874  /* Deskjet 6xx series */
875  { 601,
876    17 * 72 / 2, 14 * 72,
877    1, 1,				/* Min paper size */
878    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_300 | PCL_RES_600_600_MONO,
879    {0, 33, 18, 18},
880    {0, 33, 10, 10},	/* Check/Fix */
881    PCL_COLOR_CMYK,
882    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
883      PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
884    dj600_papersizes,
885    basic_papertypes,
886    emptylist,
887  },
888  /* Deskjet 69x series (Photo Capable) */
889  { 690,
890    17 * 72 / 2, 14 * 72,
891    1, 1,				/* Min paper size */
892    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_300 | PCL_RES_600_600,
893    {0, 33, 18, 18},
894    {0, 33, 10, 10},	/* Check/Fix */
895    PCL_COLOR_CMYK | PCL_COLOR_CMYKcm,
896    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
897      PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
898    dj600_papersizes,
899    basic_papertypes,
900    emptylist,
901  },
902  /* Deskjet 850/855/870/890 (C-RET) */
903  { 800,
904    17 * 72 / 2, 14 * 72,
905    1, 1,				/* Min paper size */
906    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600_MONO,
907    {3, 33, 18, 18},
908    {5, 33, 10, 10},
909    PCL_COLOR_CMYK | PCL_COLOR_CMYK4,
910    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
911      PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
912    dj600_papersizes,
913    basic_papertypes,
914    emptylist,
915  },
916  /* Deskjet 810C, 812C, 840C, 842C, 845C, 895C (C-RET) */
917  { 840,
918    17 * 72 / 2, 14 * 72,
919    1, 1,				/* Min paper size */
920    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_300 | PCL_RES_600_600,
921    {0, 33, 18, 18},
922    {0, 33, 10, 10},	/* Check/Fix */
923    PCL_COLOR_CMYK | PCL_COLOR_CMYK4b,
924    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
925      PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
926    dj600_papersizes,
927    basic_papertypes,
928    emptylist,
929  },
930  /* Deskjet 900 series, 1220C, PhotoSmart P1000/P1100 */
931  { 900,
932    17 * 72 / 2, 14 * 72,
933    1, 1,				/* Min paper size */
934    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600 /* | PCL_RES_1200_600 | PCL_RES_2400_600 */,
935    {3, 33, 18, 18},
936    {5, 33, 10, 10},	/* Oliver Vecernik */
937    PCL_COLOR_CMYK,
938    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
939      PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE | PCL_PRINTER_DUPLEX,
940    dj600_papersizes,
941    basic_papertypes,
942    emptylist,
943  },
944  /* Deskjet 1220C (or other large format 900) */
945  { 901,
946    13 * 72, 19 * 72,
947    1, 1,				/* Min paper size */
948    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600 /* | PCL_RES_1200_600 | PCL_RES_2400_600 */,
949    {3, 33, 18, 18},
950    {5, 33, 10, 10},
951    PCL_COLOR_CMYK,
952    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
953      PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
954    dj1220_papersizes,
955    basic_papertypes,
956    emptylist,
957  },
958  /* Deskjet 1100C, 1120C */
959  { 1100,
960    13 * 72, 19 * 72,
961    1, 1,				/* Min paper size */
962    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600_MONO,
963    {3, 33, 18, 18},
964    {5, 33, 10, 10},
965    PCL_COLOR_CMYK | PCL_COLOR_CMYK4,
966    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
967      PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
968    dj1100_papersizes,
969    basic_papertypes,
970    dj_papersources,
971  },
972  /* Deskjet 1200C */
973  { 1200,
974    17 * 72 / 2, 14 * 72,
975    1, 1,				/* Min paper size */
976    PCL_RES_150_150 | PCL_RES_300_300,
977    {12, 12, 18, 18},
978    {12, 12, 10, 10},	/* Check/Fix */
979    PCL_COLOR_CMY,
980    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
981      PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
982    dj1200_papersizes,
983    basic_papertypes,
984    dj_papersources,
985  },
986  /* Deskjet 1600C */
987  { 1600,
988    17 * 72 / 2, 14 * 72,
989    1, 1,				/* Min paper size */
990    PCL_RES_150_150 | PCL_RES_300_300,
991    {12, 12, 18, 18},
992    {12, 12, 10, 10},	/* Check/Fix */
993    PCL_COLOR_CMYK,
994    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
995      PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
996    dj1200_papersizes,
997    basic_papertypes,
998    dj_papersources,
999  },
1000  /* Deskjet 2000 */
1001  { 2000,
1002    17 * 72 / 2, 14 * 72,
1003    1, 1,				/* Min paper size */
1004    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
1005    {0, 35, 18, 18},			/* Michel Goraczko */
1006    {0, 35, 10, 10},	/* Check/Fix */
1007    PCL_COLOR_CMYK,
1008    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
1009      PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
1010    dj2000_papersizes,
1011    new_papertypes,
1012    dj_papersources,
1013  },
1014  /* Deskjet 2500 */
1015  { 2500,
1016    13 * 72, 19 * 72,
1017    1, 1,				/* Min paper size */
1018    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
1019    {12, 12, 18, 18},
1020    {12, 12, 10, 10},	/* Check/Fix */
1021    PCL_COLOR_CMYK,
1022    PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
1023      PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
1024    dj2500_papersizes,
1025    new_papertypes,
1026    dj2500_papersources,
1027  },
1028  /* LaserJet II series */
1029  { 2,
1030    17 * 72 / 2, 14 * 72,
1031    1, 1,				/* Min paper size */
1032    PCL_RES_150_150 | PCL_RES_300_300,
1033    {12, 12, 18, 18},
1034    {12, 12, 10, 10},	/* Check/Fix */
1035    PCL_COLOR_NONE,
1036    PCL_PRINTER_LJ,
1037    ljsmall_papersizes,
1038    emptylist,
1039    laserjet_papersources,
1040  },
1041  /* LaserJet IIP (TIFF but no blankline) */
1042  { 21,
1043    17 * 72 / 2, 14 * 72,
1044    1, 1,				/* Min paper size */
1045    PCL_RES_150_150 | PCL_RES_300_300,
1046    {12, 12, 18, 18},
1047    {12, 12, 10, 10},	/* Check/Fix */
1048    PCL_COLOR_NONE,
1049    PCL_PRINTER_LJ | PCL_PRINTER_TIFF,
1050    ljsmall_papersizes,
1051    emptylist,
1052    laserjet_papersources,
1053  },
1054  /* Some laser printers don't have expanded A4 margins */
1055  { 22,
1056    17 * 72 / 2, 14 * 72,
1057    1, 1,				/* Min paper size */
1058    PCL_RES_150_150 | PCL_RES_300_300,
1059    {12, 12, 18, 18},
1060    {12, 12, 18, 18},	/* Check/Fix */
1061    PCL_COLOR_NONE,
1062    PCL_PRINTER_LJ,
1063    ljsmall_papersizes,
1064    emptylist,
1065    laserjet_papersources,
1066  },
1067  /* PCL-4 with large paper */
1068  { 23,
1069    13 * 72, 19 * 72,
1070    1, 1,				/* Min paper size */
1071    PCL_RES_150_150 | PCL_RES_300_300,
1072    {12, 12, 18, 18},
1073    {12, 12, 10, 10},	/* Check/Fix */
1074    PCL_COLOR_NONE,
1075    PCL_PRINTER_LJ,
1076    ljbig_papersizes,
1077    emptylist,
1078    laserjet_papersources,
1079  },
1080  /* PCL-4 with large paper, no expanded A4 margins */
1081  { 24,
1082    13 * 72, 19 * 72,
1083    1, 1,				/* Min paper size */
1084    PCL_RES_150_150 | PCL_RES_300_300,
1085    {12, 12, 18, 18},
1086    {12, 12, 18, 18},	/* Check/Fix */
1087    PCL_COLOR_NONE,
1088    PCL_PRINTER_LJ,
1089    ljbig_papersizes,
1090    emptylist,
1091    laserjet_papersources,
1092  },
1093  /* LaserJet III series */
1094  { 3,
1095    17 * 72 / 2, 14 * 72,
1096    1, 1,				/* Min paper size */
1097    PCL_RES_150_150 | PCL_RES_300_300,
1098    {12, 12, 18, 18},
1099    {12, 12, 10, 10},	/* Check/Fix */
1100    PCL_COLOR_NONE,
1101    PCL_PRINTER_LJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
1102    ljsmall_papersizes,
1103    emptylist,
1104    laserjet_papersources,
1105  },
1106  /* LaserJet III series */
1107  { 31,
1108    17 * 72 / 2, 14 * 72,
1109    1, 1,				/* Min paper size */
1110    PCL_RES_150_150 | PCL_RES_300_300,
1111    {12, 12, 18, 18},
1112    {12, 12, 10, 10},	/* Check/Fix */
1113    PCL_COLOR_NONE,
1114    PCL_PRINTER_LJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
1115    ljsmall_papersizes,
1116    emptylist,
1117    laserjet_papersources,
1118  },
1119  /* Some laser printers don't have expanded A4 margins */
1120  { 32,
1121    17 * 72 / 2, 14 * 72,
1122    1, 1,				/* Min paper size */
1123    PCL_RES_150_150 | PCL_RES_300_300,
1124    {12, 12, 18, 18},
1125    {12, 12, 18, 18},	/* Check/Fix */
1126    PCL_COLOR_NONE,
1127    PCL_PRINTER_LJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
1128    ljsmall_papersizes,
1129    emptylist,
1130    laserjet_papersources,
1131  },
1132  /* PCL-5 with large paper */
1133  { 33,
1134    13 * 72, 19 * 72,
1135    1, 1,				/* Min paper size */
1136    PCL_RES_150_150 | PCL_RES_300_300,
1137    {12, 12, 18, 18},
1138    {12, 12, 10, 10},	/* Check/Fix */
1139    PCL_COLOR_NONE,
1140    PCL_PRINTER_LJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
1141    ljbig_papersizes,
1142    emptylist,
1143    laserjet_papersources,
1144  },
1145  /* PCL-5 with large paper, no expanded margins */
1146  { 34,
1147    13 * 72, 19 * 72,
1148    1, 1,				/* Min paper size */
1149    PCL_RES_150_150 | PCL_RES_300_300,
1150    {12, 12, 18, 18},
1151    {12, 12, 18, 18},	/* Check/Fix */
1152    PCL_COLOR_NONE,
1153    PCL_PRINTER_LJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
1154    ljbig_papersizes,
1155    emptylist,
1156    laserjet_papersources,
1157  },
1158  /* PCL-5 with tabloid paper, no expanded margins */
1159  { 35,
1160    118 * 72 / 10, 17 * 72,
1161    1, 1,				/* Min paper size */
1162    PCL_RES_150_150 | PCL_RES_300_300,
1163    {12, 12, 18, 18},
1164    {12, 12, 18, 18},	/* Check/Fix */
1165    PCL_COLOR_NONE,
1166    PCL_PRINTER_LJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
1167    ljtabloid_papersizes,
1168    emptylist,
1169    laserjet_papersources,
1170  },
1171  /* LaserJet 4L */
1172  { 4,
1173    17 * 72 / 2, 14 * 72,
1174    1, 1,				/* Min paper size */
1175    PCL_RES_150_150 | PCL_RES_300_300,
1176    {12, 12, 18, 18},
1177    {12, 12, 10, 10},	/* Check/Fix */
1178    PCL_COLOR_NONE,
1179    PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
1180    ljsmall_papersizes,
1181    emptylist,
1182    laserjet_papersources,
1183  },
1184  /* LaserJet 4V */
1185  { 5,
1186    13 * 72, 19 * 72,
1187    1, 1,				/* Min paper size */
1188    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
1189    {12, 12, 18, 18},
1190    {12, 12, 10, 10},	/* Check/Fix */
1191    PCL_COLOR_NONE,
1192    PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
1193    ljbig_papersizes,
1194    emptylist,
1195    laserjet_papersources,
1196  },
1197  /* LaserJet 4Si */
1198  { 51,
1199    13 * 72, 19 * 72,
1200    1, 1,				/* Min paper size */
1201    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
1202    {12, 12, 18, 18},
1203    {12, 12, 10, 10},	/* Check/Fix */
1204    PCL_COLOR_NONE,
1205    PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE |
1206      PCL_PRINTER_DUPLEX,
1207    ljbig_papersizes,
1208    emptylist,
1209    laserjet_papersources,
1210  },
1211  /* LaserJet 4 series (except as above), 5 series, 6 series */
1212  { 6,
1213    17 * 72 / 2, 14 * 72,
1214    1, 1,				/* Min paper size */
1215    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
1216    {12, 12, 18, 18},
1217    {12, 12, 10, 10},	/* Check/Fix */
1218    PCL_COLOR_NONE,
1219    PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE |
1220      PCL_PRINTER_DUPLEX,
1221    ljsmall_papersizes,
1222    emptylist,
1223    laserjet_papersources,
1224  },
1225  /* PCL-5c/5e/6/XL with large paper */
1226  { 61,
1227    13 * 72, 19 * 72,
1228    1, 1,				/* Min paper size */
1229    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
1230    {12, 12, 18, 18},
1231    {12, 12, 10, 10},	/* Check/Fix */
1232    PCL_COLOR_NONE,
1233    PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE |
1234      PCL_PRINTER_DUPLEX,
1235    ljbig_papersizes,
1236    emptylist,
1237    laserjet_papersources,
1238  },
1239  /* Some laser printers don't have expanded A4 margins */
1240  { 62,
1241    17 * 72 / 2, 14 * 72,
1242    1, 1,				/* Min paper size */
1243    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
1244    {12, 12, 18, 18},
1245    {12, 12, 18, 18},	/* Check/Fix */
1246    PCL_COLOR_NONE,
1247    PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE |
1248      PCL_PRINTER_DUPLEX,
1249    ljsmall_papersizes,
1250    emptylist,
1251    laserjet_papersources,
1252  },
1253  /* PCL-5c/5e/6/XL with large paper, no expanded A4 margins */
1254  { 63,
1255    13 * 72, 19 * 72,
1256    1, 1,				/* Min paper size */
1257    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
1258    {12, 12, 18, 18},
1259    {12, 12, 18, 18},	/* Check/Fix */
1260    PCL_COLOR_NONE,
1261    PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE |
1262      PCL_PRINTER_DUPLEX,
1263    ljbig_papersizes,
1264    emptylist,
1265    laserjet_papersources,
1266  },
1267  /* PCL-5c/5e/6/XL with tabloid paper, no expanded A4 margins */
1268  { 64,
1269    118 * 72 / 10, 17 * 72,
1270    1, 1,				/* Min paper size */
1271    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
1272    {12, 12, 18, 18},
1273    {12, 12, 18, 18},	/* Check/Fix */
1274    PCL_COLOR_NONE,
1275    PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE |
1276      PCL_PRINTER_DUPLEX,
1277    ljtabloid_papersizes,
1278    emptylist,
1279    laserjet_papersources,
1280  },
1281  /* LaserJet 5Si */
1282  { 7,
1283    13 * 72, 19 * 72,
1284    1, 1,				/* Min paper size */
1285    PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
1286    {12, 12, 18, 18},
1287    {12, 12, 10, 10},	/* Check/Fix */
1288    PCL_COLOR_NONE,
1289    PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE |
1290      PCL_PRINTER_DUPLEX,
1291    ljbig_papersizes,
1292    emptylist,
1293    laserjet_papersources,
1294  },
1295};
1296
1297
1298static const char standard_sat_adjustment[] =
1299"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1300"<gutenprint>\n"
1301"<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n"
1302"<sequence count=\"48\" lower-bound=\"0\" upper-bound=\"4\">\n"
1303/* C */  "1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 "  /* B */
1304/* B */  "1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 "  /* M */
1305/* M */  "1.00 0.95 0.90 0.90 0.90 0.90 0.90 0.90 "  /* R */
1306/* R */  "0.90 0.95 0.95 1.00 1.00 1.00 1.00 1.00 "  /* Y */
1307/* Y */  "1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 "  /* G */
1308/* G */  "1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 "  /* C */
1309"</sequence>\n"
1310"</curve>\n"
1311"</gutenprint>\n";
1312
1313static const char standard_lum_adjustment[] =
1314"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1315"<gutenprint>\n"
1316"<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n"
1317"<sequence count=\"48\" lower-bound=\"0\" upper-bound=\"4\">\n"
1318/* C */  "0.65 0.67 0.70 0.72 0.77 0.80 0.82 0.85 "  /* B */
1319/* B */  "0.87 0.86 0.82 0.79 0.79 0.82 0.85 0.88 "  /* M */
1320/* M */  "0.92 0.95 0.96 0.97 0.97 0.97 0.96 0.96 "  /* R */
1321/* R */  "0.96 0.97 0.97 0.98 0.99 1.00 1.00 1.00 "  /* Y */
1322/* Y */  "1.00 0.97 0.95 0.94 0.93 0.92 0.90 0.86 "  /* G */
1323/* G */  "0.79 0.76 0.71 0.68 0.68 0.68 0.68 0.66 "  /* C */
1324"</sequence>\n"
1325"</curve>\n"
1326"</gutenprint>\n";
1327
1328static const char standard_hue_adjustment[] =
1329"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1330"<gutenprint>\n"
1331"<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n"
1332"<sequence count=\"48\" lower-bound=\"-6\" upper-bound=\"6\">\n"
1333/* C */  "0.00 0.06 0.10 0.10 0.06 -.01 -.09 -.17 "  /* B */
1334/* B */  "-.25 -.33 -.38 -.38 -.36 -.34 -.34 -.34 "  /* M */
1335/* M */  "-.34 -.34 -.36 -.40 -.50 -.40 -.30 -.20 "  /* R */
1336/* R */  "-.12 -.07 -.04 -.02 0.00 0.00 0.00 0.00 "  /* Y */
1337/* Y */  "0.00 0.00 0.00 -.05 -.10 -.15 -.22 -.24 "  /* G */
1338/* G */  "-.26 -.30 -.33 -.28 -.25 -.20 -.13 -.06 "  /* C */
1339"</sequence>\n"
1340"</curve>\n"
1341"</gutenprint>\n";
1342
1343static const stp_parameter_t the_parameters[] =
1344{
1345  {
1346    "PageSize", N_("Page Size"), "Color=No,Category=Basic Printer Setup",
1347    N_("Size of the paper being printed to"),
1348    STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
1349    STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
1350  },
1351  {
1352    "MediaType", N_("Media Type"), "Color=Yes,Category=Basic Printer Setup",
1353    N_("Type of media (plain paper, photo paper, etc.)"),
1354    STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
1355    STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
1356  },
1357  {
1358    "InputSlot", N_("Media Source"), "Color=No,Category=Basic Printer Setup",
1359    N_("Source (input slot) of the media"),
1360    STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
1361    STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
1362  },
1363  {
1364    "Quality", N_("Print Quality"), "Color=Yes,Category=Basic Output Adjustment",
1365    N_("Print Quality"),
1366    STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
1367    STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0
1368  },
1369  {
1370    "Resolution", N_("Resolution"), "Color=Yes,Category=Basic Printer Setup",
1371    N_("Resolution of the print"),
1372    STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
1373    STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
1374  },
1375  {
1376    "InkType", N_("Ink Type"), "Color=Yes,Category=Advanced Printer Setup",
1377    N_("Type of ink in the printer"),
1378    STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
1379    STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
1380  },
1381  {
1382    "InkChannels", N_("Ink Channels"), "Color=Yes,Category=Advanced Printer Functionality",
1383    N_("Ink Channels"),
1384    STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
1385    STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0
1386  },
1387  {
1388    "PrintingMode", N_("Printing Mode"), "Color=Yes,Category=Core Parameter",
1389    N_("Printing Output Mode"),
1390    STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
1391    STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
1392  },
1393  {
1394    "Duplex", N_("Double-Sided Printing"), "Color=No,Category=Basic Printer Setup",
1395    N_("Duplex/Tumble Setting"),
1396    STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
1397    STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
1398  },
1399};
1400
1401static const int the_parameter_count =
1402sizeof(the_parameters) / sizeof(const stp_parameter_t);
1403
1404typedef struct
1405{
1406  const stp_parameter_t param;
1407  double min;
1408  double max;
1409  double defval;
1410  int color_only;
1411} float_param_t;
1412
1413static const float_param_t float_parameters[] =
1414{
1415  {
1416    {
1417      "CyanDensity", N_("Cyan Density"), "Color=Yes,Category=Output Level Adjustment",
1418      N_("Adjust the cyan density"),
1419      STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
1420      STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 1, 1, 0
1421    }, 0.0, 2.0, 1.0, 1
1422  },
1423  {
1424    {
1425      "MagentaDensity", N_("Magenta Density"), "Color=Yes,Category=Output Level Adjustment",
1426      N_("Adjust the magenta density"),
1427      STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
1428      STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 2, 1, 0
1429    }, 0.0, 2.0, 1.0, 1
1430  },
1431  {
1432    {
1433      "YellowDensity", N_("Yellow Density"), "Color=Yes,Category=Output Level Adjustment",
1434      N_("Adjust the yellow density"),
1435      STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
1436      STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 3, 1, 0
1437    }, 0.0, 2.0, 1.0, 1
1438  },
1439  {
1440    {
1441      "BlackDensity", N_("Black Density"), "Color=Yes,Category=Output Level Adjustment",
1442      N_("Adjust the black density"),
1443      STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
1444      STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 0, 1, 0
1445    }, 0.0, 2.0, 1.0, 1
1446  },
1447  {
1448    {
1449      "LightCyanTrans", N_("Light Cyan Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
1450      N_("Light Cyan Transition"),
1451      STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
1452      STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
1453    }, 0.0, 5.0, 1.0, 1
1454  },
1455  {
1456    {
1457      "LightMagentaTrans", N_("Light Magenta Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
1458      N_("Light Magenta Transition"),
1459      STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
1460      STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
1461    }, 0.0, 5.0, 1.0, 1
1462  },
1463};
1464
1465static const int float_parameter_count =
1466sizeof(float_parameters) / sizeof(const float_param_t);
1467
1468/*
1469 * Convert a name into it's option value
1470 */
1471
1472static int pcl_string_to_val(const char *string,		/* I: String */
1473                           const pcl_t *options,	/* I: Options */
1474			   int num_options)		/* I: Num options */
1475{
1476
1477  int i;
1478  int code = -1;
1479
1480 /*
1481  * Look up the string in the table and convert to the code.
1482  */
1483
1484  for (i=0; i<num_options; i++) {
1485    if (!strcmp(string, options[i].pcl_name)) {
1486       code=options[i].pcl_code;
1487       break;
1488       }
1489  }
1490
1491  stp_deprintf(STP_DBG_PCL, "String: %s, Code: %d\n", string, code);
1492
1493  return(code);
1494}
1495
1496/*
1497 * Convert a value into it's option name
1498 */
1499
1500static const char * pcl_val_to_string(int code,			/* I: Code */
1501                           const pcl_t *options,	/* I: Options */
1502			   int num_options)		/* I: Num options */
1503{
1504
1505  int i;
1506  const char *string = NULL;
1507
1508 /*
1509  * Look up the code in the table and convert to the string.
1510  */
1511
1512  for (i=0; i<num_options; i++) {
1513    if (code == options[i].pcl_code) {
1514       string=options[i].pcl_name;
1515       break;
1516       }
1517  }
1518
1519  stp_deprintf(STP_DBG_PCL, "Code: %d, String: %s\n", code, string);
1520
1521  return(string);
1522}
1523
1524static const char * pcl_val_to_text(int code,			/* I: Code */
1525                           const pcl_t *options,	/* I: Options */
1526			   int num_options)		/* I: Num options */
1527{
1528
1529  int i;
1530  const char *string = NULL;
1531
1532 /*
1533  * Look up the code in the table and convert to the string.
1534  */
1535
1536  for (i=0; i<num_options; i++) {
1537    if (code == options[i].pcl_code) {
1538       string=gettext(options[i].pcl_text);
1539       break;
1540       }
1541  }
1542
1543  stp_deprintf(STP_DBG_PCL, "Code: %d, String: %s\n", code, string);
1544
1545  return(string);
1546}
1547
1548static const double dot_sizes[] = { 0.5, 0.832, 1.0 };
1549static const double dot_sizes_cret[] = { 1.0, 1.0, 1.0 };
1550
1551static const stp_dotsize_t variable_dotsizes[] =
1552{
1553  { 0x1, 0.5 },
1554  { 0x2, 0.67 },
1555  { 0x3, 1.0 }
1556};
1557
1558static const stp_shade_t variable_shades[] =
1559{
1560  { 0.38, 3, variable_dotsizes },
1561  { 1.0, 3, variable_dotsizes }
1562};
1563
1564/*
1565 * pcl_get_model_capabilities() - Return struct of model capabilities
1566 */
1567
1568static const pcl_cap_t *				/* O: Capabilities */
1569pcl_get_model_capabilities(int model)	/* I: Model */
1570{
1571  int i;
1572  int models= sizeof(pcl_model_capabilities) / sizeof(pcl_cap_t);
1573  for (i=0; i<models; i++) {
1574    if (pcl_model_capabilities[i].model == model) {
1575      return &(pcl_model_capabilities[i]);
1576    }
1577  }
1578  stp_erprintf("pcl: model %d not found in capabilities list.\n",model);
1579  return &(pcl_model_capabilities[0]);
1580}
1581
1582/*
1583 * Determine the current resolution based on quality and resolution settings
1584 */
1585
1586static void
1587pcl_describe_resolution(const stp_vars_t *v, int *x, int *y)
1588{
1589  int i;
1590  int model = stp_get_model_id(v);
1591  const char *resolution = stp_get_string_parameter(v, "Resolution");
1592  const char *quality;
1593  const pcl_cap_t *caps = NULL;
1594  if (resolution)
1595    {
1596      for (i = 0; i < NUM_RESOLUTIONS; i++)
1597	{
1598	  if (!strcmp(resolution, pcl_resolutions[i].pcl_name))
1599	    {
1600	      *x = pcl_resolutions[i].p0;
1601	      *y = pcl_resolutions[i].p1;
1602	      return;
1603	    }
1604	}
1605    }
1606  quality = stp_get_string_parameter(v, "Quality");
1607  caps = pcl_get_model_capabilities(model);
1608  if (quality && strcmp(quality, "None") == 0)
1609    quality = "Standard";
1610  if (quality)
1611    {
1612      for (i = 0; i < NUM_QUALITIES; i++)
1613	{
1614	  if ((caps->resolutions & pcl_qualities[i].pcl_code) &&
1615	      !strcmp(quality, pcl_qualities[i].pcl_name))
1616	    {
1617	      *x = pcl_qualities[i].p0;
1618	      *y = pcl_qualities[i].p1;
1619	      return;
1620	    }
1621	}
1622    }
1623  *x = -1;
1624  *y = -1;
1625}
1626
1627/*
1628 * Convert Media size name into PCL media code for printer
1629 */
1630
1631static int pcl_convert_media_size(const char *media_size,	/* I: Media size string */
1632				  int  model)		/* I: model number */
1633{
1634
1635  int i;
1636  int media_code = 0;
1637  const pcl_cap_t *caps;
1638
1639 /*
1640  * First look up the media size in the table and convert to the code.
1641  */
1642
1643  media_code = pcl_string_to_val(media_size, pcl_media_sizes,
1644                                 NUM_PRINTER_PAPER_SIZES);
1645
1646  stp_deprintf(STP_DBG_PCL, "Media Size: %s, Code: %d\n", media_size, media_code);
1647
1648 /*
1649  * Now see if the printer supports the code found.
1650  */
1651
1652  if (media_code != -1) {
1653    caps = pcl_get_model_capabilities(model);
1654
1655    for (i=0; (i<NUM_PRINTER_PAPER_SIZES) && (caps->paper_sizes[i] != -1); i++) {
1656      if (media_code == (int) caps->paper_sizes[i])
1657        return(media_code);		/* Is supported */
1658    }
1659
1660    stp_deprintf(STP_DBG_PCL, "Media Code %d not supported by printer model %d.\n",
1661      media_code, model);
1662    return(-1);				/* Not supported */
1663  }
1664  else
1665    return(-1);				/* Not supported */
1666}
1667
1668
1669static const stp_param_string_t ink_types[] =
1670{
1671  { "CMYK",	N_ ("Color + Black Cartridges") },
1672  { "Photo",	N_ ("Color + Photo Cartridges") }
1673};
1674
1675/*
1676 * Duplex support - modes available
1677 * Note that the internal names MUST match those in cups/genppd.c else the
1678 * PPD files will not be generated correctly
1679 */
1680
1681static const stp_param_string_t duplex_types[] =
1682{
1683  { "None",		N_ ("Off") },
1684  { "DuplexNoTumble",	N_ ("Long Edge (Standard)") },
1685  { "DuplexTumble",	N_ ("Short Edge (Flip)") }
1686};
1687#define NUM_DUPLEX (sizeof (duplex_types) / sizeof (stp_param_string_t))
1688
1689/*
1690 * 'pcl_papersize_valid()' - Is the paper size valid for this printer.
1691 */
1692
1693static int
1694pcl_papersize_valid(const stp_papersize_t *pt,
1695		    int model)
1696{
1697
1698  const pcl_cap_t *caps = pcl_get_model_capabilities(model);
1699
1700#ifdef PCL_NO_CUSTOM_PAPERSIZES
1701  int use_custom = 0;
1702#else
1703  int use_custom = ((caps->stp_printer_type & PCL_PRINTER_CUSTOM_SIZE)
1704                     == PCL_PRINTER_CUSTOM_SIZE);
1705#endif
1706
1707  unsigned int pwidth = pt->width;
1708  unsigned int pheight = pt->height;
1709
1710/*
1711 * This function decides whether a paper size is allowed for the
1712 * current printer. The DeskJet feed mechanisms set a minimum and
1713 * maximum size for the paper, BUT some of the directly supported
1714 * media sizes are less than this minimum (eg card and envelopes)
1715 * So, we allow supported sizes though, but clamp custom sizes
1716 * to the min and max sizes.
1717 */
1718
1719/*
1720 * Is it a valid name?
1721 */
1722
1723  if (strlen(pt->name) <= 0)
1724    return(0);
1725
1726/*
1727 * Is it a recognised supported name?
1728 */
1729
1730  if (pcl_convert_media_size(pt->name, model) != -1)
1731    return(1);
1732
1733/*
1734 * If we are not allowed to use custom paper sizes, we are done
1735 */
1736
1737  if (use_custom == 0)
1738    return(0);
1739
1740/*
1741 * We are allowed custom paper sizes. Check that the size is within
1742 * limits.
1743 */
1744
1745  if (pwidth <= caps->custom_max_width &&
1746     pheight <= caps->custom_max_height &&
1747     (pheight >=  caps->custom_min_height || pheight == 0) &&
1748     (pwidth >= caps->custom_min_width || pwidth == 0))
1749    return(1);
1750
1751  return(0);
1752}
1753
1754/*
1755 * 'pcl_parameters()' - Return the parameter values for the given parameter.
1756 */
1757
1758static stp_parameter_list_t
1759pcl_list_parameters(const stp_vars_t *v)
1760{
1761  stp_parameter_list_t *ret = stp_parameter_list_create();
1762  int i;
1763  for (i = 0; i < the_parameter_count; i++)
1764    stp_parameter_list_add_param(ret, &(the_parameters[i]));
1765  for (i = 0; i < float_parameter_count; i++)
1766    stp_parameter_list_add_param(ret, &(float_parameters[i].param));
1767  return ret;
1768}
1769
1770static void
1771pcl_parameters(const stp_vars_t *v, const char *name,
1772	       stp_parameter_t *description)
1773{
1774  int		model = stp_get_model_id(v);
1775  int		i;
1776  const pcl_cap_t *caps;
1777  description->p_type = STP_PARAMETER_TYPE_INVALID;
1778
1779  if (name == NULL)
1780    return;
1781
1782  stp_deprintf(STP_DBG_PCL, "pcl_parameters(): Name = %s\n", name);
1783
1784  caps = pcl_get_model_capabilities(model);
1785
1786  stp_deprintf(STP_DBG_PCL, "Printer model = %d\n", model);
1787  stp_deprintf(STP_DBG_PCL, "PageWidth = %d, PageHeight = %d\n", caps->custom_max_width, caps->custom_max_height);
1788  stp_deprintf(STP_DBG_PCL, "MinPageWidth = %d, MinPageHeight = %d\n", caps->custom_min_width, caps->custom_min_height);
1789  stp_deprintf(STP_DBG_PCL, "Normal Margins: top = %d, bottom = %d, left = %d, right = %d\n",
1790    caps->normal_margins.top_margin, caps->normal_margins.bottom_margin,
1791    caps->normal_margins.left_margin, caps->normal_margins.right_margin);
1792  stp_deprintf(STP_DBG_PCL, "A4 Margins: top = %d, bottom = %d, left = %d, right = %d\n",
1793    caps->a4_margins.top_margin, caps->a4_margins.bottom_margin,
1794    caps->a4_margins.left_margin, caps->a4_margins.right_margin);
1795  stp_deprintf(STP_DBG_PCL, "Resolutions: %d\n", caps->resolutions);
1796  stp_deprintf(STP_DBG_PCL, "ColorType = %d, PrinterType = %d\n", caps->color_type, caps->stp_printer_type);
1797
1798  for (i = 0; i < the_parameter_count; i++)
1799    if (strcmp(name, the_parameters[i].name) == 0)
1800      {
1801	stp_fill_parameter_settings(description, &(the_parameters[i]));
1802	break;
1803      }
1804  description->deflt.str = NULL;
1805
1806  for (i = 0; i < float_parameter_count; i++)
1807    if (strcmp(name, float_parameters[i].param.name) == 0)
1808      {
1809	stp_fill_parameter_settings(description,
1810				    &(float_parameters[i].param));
1811	description->deflt.dbl = float_parameters[i].defval;
1812	description->bounds.dbl.upper = float_parameters[i].max;
1813	description->bounds.dbl.lower = float_parameters[i].min;
1814	break;
1815      }
1816
1817  if (strcmp(name, "PageSize") == 0)
1818    {
1819      int papersizes = stp_known_papersizes();
1820      description->bounds.str = stp_string_list_create();
1821      for (i = 0; i < papersizes; i++)
1822	{
1823	  const stp_papersize_t *pt = stp_get_papersize_by_index(i);
1824	  if (strlen(pt->name) > 0 && pcl_papersize_valid(pt, model))
1825	    stp_string_list_add_string(description->bounds.str,
1826				       pt->name, gettext(pt->text));
1827	}
1828      description->deflt.str =
1829	stp_string_list_param(description->bounds.str, 0)->name;
1830    }
1831  else if (strcmp(name, "MediaType") == 0)
1832  {
1833    description->bounds.str = stp_string_list_create();
1834    if (caps->paper_types[0] != -1)
1835      {
1836	for (i=0; (i < NUM_PRINTER_PAPER_TYPES) && (caps->paper_types[i] != -1); i++)
1837	  stp_string_list_add_string(description->bounds.str,
1838				    pcl_val_to_string(caps->paper_types[i],
1839						      pcl_media_types,
1840						      NUM_PRINTER_PAPER_TYPES),
1841				    pcl_val_to_text(caps->paper_types[i],
1842						    pcl_media_types,
1843						    NUM_PRINTER_PAPER_TYPES));
1844	description->deflt.str =
1845	  stp_string_list_param(description->bounds.str, 0)->name;
1846      }
1847    else
1848      description->is_active = 0;
1849  }
1850  else if (strcmp(name, "InputSlot") == 0)
1851  {
1852    description->bounds.str = stp_string_list_create();
1853    if (caps->paper_sources[0] != -1)
1854      {
1855	for (i=0; (i < NUM_PRINTER_PAPER_SOURCES) && (caps->paper_sources[i] != -1); i++)
1856	  stp_string_list_add_string(description->bounds.str,
1857				    pcl_val_to_string(caps->paper_sources[i],
1858						      pcl_media_sources,
1859						      NUM_PRINTER_PAPER_SOURCES),
1860				    pcl_val_to_text(caps->paper_sources[i],
1861						    pcl_media_sources,
1862						    NUM_PRINTER_PAPER_SOURCES));
1863	description->deflt.str =
1864	  stp_string_list_param(description->bounds.str, 0)->name;
1865      }
1866    else
1867      description->is_active = 0;
1868  }
1869  else if (strcmp(name, "Resolution") == 0)
1870  {
1871    description->bounds.str = stp_string_list_create();
1872    stp_string_list_add_string(description->bounds.str, "None", _("Default"));
1873    description->deflt.str = "None";
1874    for (i = 0; i < NUM_RESOLUTIONS; i++)
1875      if (caps->resolutions & pcl_resolutions[i].pcl_code)
1876	{
1877	  stp_string_list_add_string
1878	    (description->bounds.str,
1879	     pcl_val_to_string(pcl_resolutions[i].pcl_code,
1880			       pcl_resolutions, NUM_RESOLUTIONS),
1881	     pcl_val_to_text(pcl_resolutions[i].pcl_code,
1882			     pcl_resolutions, NUM_RESOLUTIONS));
1883	}
1884  }
1885  else if (strcmp(name, "Quality") == 0)
1886  {
1887    int has_standard_quality = 0;
1888    description->bounds.str = stp_string_list_create();
1889    stp_string_list_add_string(description->bounds.str, "None",
1890			       _("Manual Control"));
1891    for (i = 0; i < NUM_QUALITIES; i++)
1892      if (caps->resolutions & pcl_qualities[i].pcl_code)
1893	{
1894	  const char *qual =
1895	    pcl_val_to_string(pcl_qualities[i].pcl_code,
1896			      pcl_qualities, NUM_QUALITIES);
1897	  if (! stp_string_list_is_present(description->bounds.str, qual))
1898	    stp_string_list_add_string
1899	      (description->bounds.str, qual,
1900	       pcl_val_to_text(pcl_qualities[i].pcl_code,
1901			       pcl_qualities, NUM_QUALITIES));
1902	  if (strcmp(qual, "Standard") == 0)
1903	    has_standard_quality = 1;
1904	}
1905    if (has_standard_quality)
1906      description->deflt.str = "Standard";
1907    else
1908      description->deflt.str = "None";
1909  }
1910  else if (strcmp(name, "InkType") == 0)
1911  {
1912    description->bounds.str = stp_string_list_create();
1913    if (caps->color_type & PCL_COLOR_CMYKcm)
1914    {
1915      description->deflt.str = ink_types[0].name;
1916      stp_string_list_add_string(description->bounds.str,
1917			       ink_types[0].name,gettext(ink_types[0].text));
1918      stp_string_list_add_string(description->bounds.str,
1919			       ink_types[1].name,gettext(ink_types[1].text));
1920    }
1921    else
1922      description->is_active = 0;
1923  }
1924  else if (strcmp(name, "Duplex") == 0)
1925  {
1926    int offer_duplex=0;
1927
1928    description->bounds.str = stp_string_list_create();
1929
1930/*
1931 * Don't offer the Duplex/Tumble options if the JobMode parameter is
1932 * set to "Page" Mode.
1933 * "Page" mode is set by the Gimp Plugin, which only outputs one page at a
1934 * time, so Duplex/Tumble is meaningless.
1935 */
1936
1937    if (stp_get_string_parameter(v, "JobMode"))
1938        offer_duplex = strcmp(stp_get_string_parameter(v, "JobMode"), "Page");
1939    else
1940     offer_duplex=1;
1941
1942    if (offer_duplex)
1943    {
1944      if (caps->stp_printer_type & PCL_PRINTER_DUPLEX)
1945      {
1946        description->deflt.str = duplex_types[0].name;
1947        for (i=0; i < NUM_DUPLEX; i++)
1948        {
1949          stp_string_list_add_string(description->bounds.str,
1950			       duplex_types[i].name,gettext(duplex_types[i].text));
1951        }
1952      }
1953      else
1954        description->is_active = 0;	/* Not supported by printer */
1955    }
1956    else
1957      description->is_active = 0;	/* Not in "Job" mode */
1958  }
1959  else if (strcmp(name, "CyanDensity") == 0 ||
1960	   strcmp(name, "MagentaDensity") == 0 ||
1961	   strcmp(name, "YellowDensity") == 0 ||
1962	   strcmp(name, "BlackDensity") == 0)
1963    {
1964      if (caps->color_type != PCL_COLOR_NONE &&
1965	  stp_check_string_parameter(v, "PrintingMode", STP_PARAMETER_DEFAULTED) &&
1966	  strcmp(stp_get_string_parameter(v, "PrintingMode"), "Color") == 0)
1967	description->is_active = 1;
1968      else
1969	description->is_active = 0;
1970    }
1971  else if (strcmp(name, "LightCyanTrans") == 0 ||
1972	   strcmp(name, "LightMagentaTrans") == 0)
1973    {
1974      if (caps->color_type & PCL_COLOR_CMYKcm &&
1975	  stp_check_string_parameter(v, "PrintingMode", STP_PARAMETER_DEFAULTED) &&
1976	  strcmp(stp_get_string_parameter(v, "PrintingMode"), "Color") == 0)
1977	description->is_active = 1;
1978      else
1979	description->is_active = 0;
1980    }
1981  else if (strcmp(name, "InkChannels") == 0)
1982    {
1983      if (caps->color_type & PCL_COLOR_CMYKcm)
1984	description->deflt.integer = 6;
1985      else if (caps->color_type == PCL_COLOR_NONE)
1986	description->deflt.integer = 1;
1987      else
1988	description->deflt.integer = 4;
1989      description->bounds.integer.lower = -1;
1990      description->bounds.integer.upper = -1;
1991    }
1992  else if (strcmp(name, "PrintingMode") == 0)
1993    {
1994      description->bounds.str = stp_string_list_create();
1995      if (caps->color_type != PCL_COLOR_NONE)
1996	stp_string_list_add_string
1997	  (description->bounds.str, "Color", _("Color"));
1998      stp_string_list_add_string
1999	(description->bounds.str, "BW", _("Black and White"));
2000      description->deflt.str =
2001	stp_string_list_param(description->bounds.str, 0)->name;
2002    }
2003}
2004
2005
2006/*
2007 * 'pcl_imageable_area()' - Return the imageable area of the page.
2008 */
2009static void
2010internal_imageable_area(const stp_vars_t *v,     /* I */
2011			int  use_paper_margins,
2012			int  *left,	/* O - Left position in points */
2013			int  *right,	/* O - Right position in points */
2014			int  *bottom,	/* O - Bottom position in points */
2015			int  *top)	/* O - Top position in points */
2016{
2017  int	width, height;			/* Size of page */
2018  const pcl_cap_t *caps;		/* Printer caps */
2019  int	pcl_media_size;			/* Converted media size */
2020  const char *media_size = stp_get_string_parameter(v, "PageSize");
2021  const stp_papersize_t *pp = NULL;
2022  int left_margin = 0;
2023  int right_margin = 0;
2024  int bottom_margin = 0;
2025  int top_margin = 0;
2026
2027  caps = pcl_get_model_capabilities(stp_get_model_id(v));
2028
2029  stp_default_media_size(v, &width, &height);
2030
2031/* If we are using A4 paper, then the margins are different than any
2032 * other paper size. This is because HP wanted to have the same printable
2033 * width for A4 as for letter. Go figure.
2034 */
2035
2036  if (!media_size)
2037    media_size = "";
2038  if (strlen(media_size) == 0 &&
2039      ((pp = stp_get_papersize_by_size(stp_get_page_height(v),
2040				       stp_get_page_width(v))) != NULL))
2041    media_size = pp->name;
2042
2043  stp_deprintf(STP_DBG_PCL, "pcl_imageable_area(): media_size: '%s'\n",
2044	       media_size);
2045
2046  pcl_media_size = pcl_convert_media_size(media_size, stp_get_model_id(v));
2047  if (media_size)
2048    pp = stp_get_papersize_by_name(media_size);
2049  if (pp && use_paper_margins)
2050    {
2051      left_margin = pp->left;
2052      right_margin = pp->right;
2053      bottom_margin = pp->bottom;
2054      top_margin = pp->top;
2055    }
2056
2057  if (pcl_media_size == PCL_PAPERSIZE_A4)
2058  {
2059    left_margin = MAX(left_margin, caps->a4_margins.left_margin);
2060    right_margin = MAX(right_margin, caps->a4_margins.right_margin);
2061    top_margin = MAX(top_margin, caps->a4_margins.top_margin);
2062    bottom_margin = MAX(bottom_margin, caps->a4_margins.bottom_margin);
2063  }
2064  else
2065  {
2066    left_margin = MAX(left_margin, caps->normal_margins.left_margin);
2067    right_margin = MAX(right_margin, caps->normal_margins.right_margin);
2068    top_margin = MAX(top_margin, caps->normal_margins.top_margin);
2069    bottom_margin = MAX(bottom_margin, caps->normal_margins.bottom_margin);
2070  }
2071  *left =	left_margin;
2072  *right =	width - right_margin;
2073  *top =	top_margin;
2074  *bottom =	height - bottom_margin;
2075}
2076
2077static void
2078pcl_imageable_area(const stp_vars_t *v,     /* I */
2079                   int  *left,		/* O - Left position in points */
2080                   int  *right,		/* O - Right position in points */
2081                   int  *bottom,	/* O - Bottom position in points */
2082                   int  *top)		/* O - Top position in points */
2083{
2084  internal_imageable_area(v, 1, left, right, bottom, top);
2085}
2086
2087static void
2088pcl_limit(const stp_vars_t *v,  		/* I */
2089	  int *width,
2090	  int *height,
2091	  int *min_width,
2092	  int *min_height)
2093{
2094  const pcl_cap_t *caps= pcl_get_model_capabilities(stp_get_model_id(v));
2095  *width =	caps->custom_max_width;
2096  *height =	caps->custom_max_height;
2097  *min_width =	caps->custom_min_width;
2098  *min_height =	caps->custom_min_height;
2099}
2100
2101static const char *
2102pcl_describe_output(const stp_vars_t *v)
2103{
2104  int printing_color = 0;
2105  int model = stp_get_model_id(v);
2106  const pcl_cap_t *caps = pcl_get_model_capabilities(model);
2107  const char *print_mode = stp_get_string_parameter(v, "PrintingMode");
2108  int xdpi, ydpi;
2109
2110  pcl_describe_resolution(v, &xdpi, &ydpi);
2111  if (!print_mode || strcmp(print_mode, "Color") == 0)
2112    printing_color = 1;
2113  if (((caps->resolutions & PCL_RES_600_600_MONO) == PCL_RES_600_600_MONO) &&
2114      printing_color && xdpi == 600 && ydpi == 600)
2115    printing_color = 0;
2116  if (printing_color)
2117    {
2118      if ((caps->color_type & PCL_COLOR_CMY) == PCL_COLOR_CMY)
2119	return "CMY";
2120      else
2121	return "CMYK";
2122    }
2123  else
2124    return "Grayscale";
2125}
2126
2127/*
2128 * 'pcl_print()' - Print an image to an HP printer.
2129 */
2130
2131static void
2132pcl_printfunc(stp_vars_t *v)
2133{
2134  pcl_privdata_t *pd = (pcl_privdata_t *) stp_get_component_data(v, "Driver");
2135  int do_blank = pd->do_blank;
2136  unsigned char *black = stp_dither_get_channel(v, STP_ECOLOR_K, 0);
2137  unsigned char *cyan = stp_dither_get_channel(v, STP_ECOLOR_C, 0);
2138  unsigned char *lcyan = stp_dither_get_channel(v, STP_ECOLOR_C, 1);
2139  unsigned char *magenta = stp_dither_get_channel(v, STP_ECOLOR_M, 0);
2140  unsigned char *lmagenta = stp_dither_get_channel(v, STP_ECOLOR_M, 1);
2141  unsigned char *yellow = stp_dither_get_channel(v, STP_ECOLOR_Y, 0);
2142  int len_c = stp_dither_get_last_position(v, STP_ECOLOR_C, 0);
2143  int len_lc = stp_dither_get_last_position(v, STP_ECOLOR_C, 1);
2144  int len_m = stp_dither_get_last_position(v, STP_ECOLOR_M, 0);
2145  int len_lm = stp_dither_get_last_position(v, STP_ECOLOR_M, 1);
2146  int len_y = stp_dither_get_last_position(v, STP_ECOLOR_Y, 0);
2147  int len_k = stp_dither_get_last_position(v, STP_ECOLOR_K, 0);
2148  int is_blank = (do_blank && (len_c == -1) && (len_lc == -1) &&
2149		  (len_m == -1) && (len_lm == -1) && (len_y == -1) &&
2150		  (len_k == -1));
2151  int height = pd->height;
2152  const char    *print_mode = stp_get_string_parameter(v, "PrintingMode");
2153
2154  if (is_blank && (pd->blank_lines != 0))	/* repeated blank line */
2155    {
2156      pd->blank_lines++;
2157    }
2158  else				/* Not blank, or is first one */
2159    {
2160      if (! is_blank)
2161	{
2162	  if (pd->blank_lines > 1)		/* Output accumulated lines */
2163	    {
2164	      pd->blank_lines--;		/* correct for one already output */
2165	      stp_deprintf(STP_DBG_PCL, "Blank Lines = %d\n", pd->blank_lines);
2166	      stp_zprintf(v, "\033*b%dY", pd->blank_lines);
2167	      pd->blank_lines=0;
2168	    }
2169	  else;
2170	}
2171      else
2172	{
2173	  pd->blank_lines++;
2174	}
2175
2176      if (pd->do_cret)
2177	{
2178	  /*
2179	   * 4-level (CRet) dithers...
2180	   */
2181	  if (strcmp(print_mode, "BW") == 0)
2182	    {
2183	      (*(pd->writefunc))(v, black + height / 2, height / 2, 0);
2184	      (*(pd->writefunc))(v, black, height / 2, 1);
2185	    }
2186	  else
2187	    {
2188	      if(pd->do_cretb)
2189		{
2190		  /*	    (*(pd->writefunc))(v, black + height / 2, 0, 0); */
2191		  (*(pd->writefunc))(v, black, height/2, 0);
2192		}
2193	      else
2194		{
2195		  (*(pd->writefunc))(v, black + height / 2, height / 2, 0);
2196		  (*(pd->writefunc))(v, black, height / 2, 0);
2197		}
2198	      (*(pd->writefunc))(v, cyan + height / 2, height / 2, 0);
2199	      (*(pd->writefunc))(v, cyan, height / 2, 0);
2200	      (*(pd->writefunc))(v, magenta + height / 2, height / 2, 0);
2201	      (*(pd->writefunc))(v, magenta, height / 2, 0);
2202	      (*(pd->writefunc))(v, yellow + height / 2, height / 2, 0);
2203	      if (pd->do_6color)
2204		{
2205		  (*(pd->writefunc))(v, yellow, height / 2, 0);
2206		  (*(pd->writefunc))(v, lcyan + height / 2, height / 2, 0);
2207		  (*(pd->writefunc))(v, lcyan, height / 2, 0);
2208		  (*(pd->writefunc))(v, lmagenta + height / 2, height / 2, 0);
2209		  (*(pd->writefunc))(v, lmagenta, height / 2, 1);		/* Last plane set on light magenta */
2210		}
2211	      else
2212		(*(pd->writefunc))(v, yellow, height / 2, 1);		/* Last plane set on yellow */
2213	    }
2214	}
2215      else
2216	{
2217	  /*
2218	   * Standard 2-level dithers...
2219	   */
2220
2221	  if (strcmp(print_mode, "BW") == 0)
2222	    {
2223	      (*(pd->writefunc))(v, black, height, 1);
2224	    }
2225	  else
2226	    {
2227	      if (black != NULL)
2228		(*(pd->writefunc))(v, black, height, 0);
2229	      (*(pd->writefunc))(v, cyan, height, 0);
2230	      (*(pd->writefunc))(v, magenta, height, 0);
2231	      if (pd->do_6color)
2232		{
2233		  (*(pd->writefunc))(v, yellow, height, 0);
2234		  (*(pd->writefunc))(v, lcyan, height, 0);
2235		  (*(pd->writefunc))(v, lmagenta, height, 1);		/* Last plane set on light magenta */
2236		}
2237	      else
2238		(*(pd->writefunc))(v, yellow, height, 1);		/* Last plane set on yellow */
2239	    }
2240	}
2241    }
2242}
2243
2244static double
2245get_double_param(stp_vars_t *v, const char *param)
2246{
2247  if (param && stp_check_float_parameter(v, param, STP_PARAMETER_ACTIVE))
2248    return stp_get_float_parameter(v, param);
2249  else
2250    return 1.0;
2251}
2252
2253static int
2254pcl_do_print(stp_vars_t *v, stp_image_t *image)
2255{
2256  pcl_privdata_t privdata;
2257  int		status = 1;
2258  int		model = stp_get_model_id(v);
2259  const char	*media_size = stp_get_string_parameter(v, "PageSize");
2260  const char	*media_type = stp_get_string_parameter(v, "MediaType");
2261  const char	*media_source = stp_get_string_parameter(v, "InputSlot");
2262  const char	*ink_type = stp_get_string_parameter(v, "InkType");
2263  const char	*print_mode = stp_get_string_parameter(v, "PrintingMode");
2264  const char	*duplex_mode = stp_get_string_parameter(v, "Duplex");
2265  int		page_number = stp_get_int_parameter(v, "PageNumber");
2266  int		printing_color = 0;
2267  int		top = stp_get_top(v);
2268  int		left = stp_get_left(v);
2269  int		y;		/* Looping vars */
2270  int		xdpi, ydpi;	/* Resolution */
2271  unsigned char *black,		/* Black bitmap data */
2272		*cyan,		/* Cyan bitmap data */
2273		*magenta,	/* Magenta bitmap data */
2274		*yellow,	/* Yellow bitmap data */
2275		*lcyan,		/* Light Cyan bitmap data */
2276		*lmagenta;	/* Light Magenta bitmap data */
2277  int		page_width,	/* Width of page */
2278		page_height,	/* Height of page */
2279		page_left,
2280		page_top,
2281		page_right,
2282		page_bottom,
2283		out_width,	/* Width of image on page */
2284		out_height,	/* Height of image on page */
2285		out_channels,	/* Output bytes per pixel */
2286		errdiv,		/* Error dividend */
2287		errmod,		/* Error modulus */
2288		errval,		/* Current error value */
2289		errline,	/* Current raster line */
2290		errlast;	/* Last raster line loaded */
2291  unsigned	zero_mask;
2292  int           image_height,
2293                image_width;
2294  const pcl_cap_t *caps;		/* Printer capabilities */
2295  int		planes = 3;	/* # of output planes */
2296  int		pcl_media_size; /* PCL media size code */
2297  const double *dot_sizes_use;
2298  const stp_papersize_t *pp;
2299  int		the_top_margin,	/* Corrected top margin */
2300		the_left_margin;	/* Corrected left margin */
2301  int		manual_feed_left_adjust = 0;
2302  int		extra_left_margin = 0;
2303  stp_curve_t   *lum_adjustment;
2304  stp_curve_t   *hue_adjustment;
2305  double density;
2306
2307  if (!stp_verify(v))
2308    {
2309      stp_eprintf(v, "Print options not verified; cannot print.\n");
2310      return 0;
2311    }
2312  if (strcmp(print_mode, "Color") == 0)
2313    printing_color = 1;
2314
2315  caps = pcl_get_model_capabilities(model);
2316
2317 /*
2318  * Setup a read-only pixel region for the entire image...
2319  */
2320
2321  stp_image_init(image);
2322  image_height = stp_image_height(image);
2323  image_width = stp_image_width(image);
2324
2325 /*
2326  * Figure out the output resolution...
2327  */
2328
2329  pcl_describe_resolution(v, &xdpi, &ydpi);
2330
2331  stp_deprintf(STP_DBG_PCL,"pcl: resolution=%dx%d\n",xdpi,ydpi);
2332  if (xdpi <= 0 || ydpi <= 0)
2333    {
2334      stp_eprintf(v, "No resolution found; cannot print.\n");
2335      return 0;
2336    }
2337
2338 /*
2339  * Choose the correct color conversion function...
2340  */
2341  if (((caps->resolutions & PCL_RES_600_600_MONO) == PCL_RES_600_600_MONO) &&
2342      printing_color && xdpi == 600 && ydpi == 600)
2343    {
2344      stp_eprintf(v, "600x600 resolution only available in MONO\n");
2345      stp_set_string_parameter(v, "PrintingMode", "BW");
2346      printing_color = 0;
2347    }
2348
2349  privdata.do_cret = (xdpi >= 300 &&
2350	     ((caps->color_type & PCL_COLOR_CMYK4) == PCL_COLOR_CMYK4));
2351  privdata.do_cretb = (xdpi >= 600 && ydpi >= 600 &&
2352	      ((caps->color_type & PCL_COLOR_CMYK4b) == PCL_COLOR_CMYK4b) &&
2353	      printing_color);
2354  if (privdata.do_cretb){
2355    privdata.do_cret = 1;
2356    dot_sizes_use=dot_sizes_cret;
2357  }else{
2358    dot_sizes_use=dot_sizes;
2359  }
2360
2361  stp_deprintf(STP_DBG_PCL, "privdata.do_cret = %d\n", privdata.do_cret);
2362  stp_deprintf(STP_DBG_PCL, "privdata.do_cretb = %d\n", privdata.do_cretb);
2363
2364  if (ink_type && printing_color)
2365    privdata.do_6color = (strcmp(ink_type, "Photo") == 0);
2366  else
2367    privdata.do_6color = 0;
2368
2369  stp_deprintf(STP_DBG_PCL, "privdata.do_6color = %d\n", privdata.do_6color);
2370
2371 /*
2372  * Compute the output size...
2373  */
2374
2375  out_width = stp_get_width(v);
2376  out_height = stp_get_height(v);
2377
2378  internal_imageable_area(v, 0, &page_left, &page_right,
2379			  &page_bottom, &page_top);
2380  left -= page_left;
2381  top -= page_top;
2382  page_width = page_right - page_left;
2383  page_height = page_bottom - page_top;
2384
2385  image_height = stp_image_height(image);
2386  image_width = stp_image_width(image);
2387
2388 /*
2389  * Set media size here because it is needed by the margin calculation code.
2390  */
2391
2392  if (!media_size)
2393    media_size = "";
2394  if (strlen(media_size) == 0 &&
2395      ((pp = stp_get_papersize_by_size(stp_get_page_height(v),
2396				       stp_get_page_width(v))) != NULL))
2397    media_size = pp->name;
2398
2399  pcl_media_size = pcl_convert_media_size(media_size, model);
2400
2401  stp_deprintf(STP_DBG_PCL,"pcl_media_size = %d, media_size = %s\n", pcl_media_size, media_size);
2402
2403 /*
2404  * If the media size requested is unknown, try it as a custom size.
2405  *
2406  * Warning: The margins may need to be fixed for this!
2407  */
2408
2409  if (pcl_media_size == -1) {
2410    stp_deprintf(STP_DBG_PCL, "Paper size %s is not directly supported by printer.\n",
2411      media_size);
2412    stp_deprintf(STP_DBG_PCL, "Trying as custom pagesize (watch the margins!)\n");
2413    pcl_media_size = PCL_PAPERSIZE_CUSTOM;			/* Custom */
2414  }
2415
2416  stp_deprintf(STP_DBG_PCL, "Duplex: %s, Page_Number: %d\n", duplex_mode, page_number);
2417  privdata.duplex=0;
2418  privdata.tumble=0;
2419
2420 /*
2421  * Duplex
2422  */
2423
2424  if (duplex_mode)
2425    {
2426      if (caps->stp_printer_type & PCL_PRINTER_DUPLEX)
2427        {
2428          if ((strcmp(duplex_mode, "DuplexTumble") == 0) || (strcmp(duplex_mode, "DuplexNoTumble") == 0))
2429            privdata.duplex=1;
2430          if ((strcmp(duplex_mode, "DuplexTumble") == 0))
2431            privdata.tumble=1;
2432        }
2433    }
2434
2435 /*
2436  * Send PCL initialization commands...
2437  */
2438
2439  if ((privdata.duplex == 0) || ((page_number & 1) == 0))
2440    {
2441      int pcl_media_type,	/* PCL media type code */
2442          pcl_media_source;	/* PCL media source code */
2443
2444      stp_deprintf(STP_DBG_PCL, "Normal init\n");
2445
2446      if (privdata.do_cretb)
2447        stp_puts("\033*rbC", v);	/* End raster graphics */
2448      stp_puts("\033E", v); 				/* PCL reset */
2449      if (privdata.do_cretb)
2450        stp_zprintf(v, "\033%%-12345X@PJL ENTER LANGUAGE=PCL3GUI\n");
2451
2452      stp_puts("\033&l6D\033&k12H",v);		/* 6 lines per inch, 10 chars per inch */
2453      stp_puts("\033&l0O",v);			/* Portrait */
2454
2455      stp_zprintf(v, "\033&l%dA", pcl_media_size);	/* Set media size we calculated above */
2456      stp_zprintf(v, "\033&l%dP", stp_get_page_height(v) / 12);
2457						/* Length of "forms" in "lines" */
2458      stp_puts("\033&l0L", v);			/* Turn off perforation skip */
2459      stp_puts("\033&l0E", v);			/* Reset top margin to 0 */
2460
2461 /*
2462  * Convert media source string to the code, if specified.
2463  */
2464
2465      if (media_source && strlen(media_source) != 0) {
2466        pcl_media_source = pcl_string_to_val(media_source, pcl_media_sources,
2467                             sizeof(pcl_media_sources) / sizeof(pcl_t));
2468
2469        stp_deprintf(STP_DBG_PCL,"pcl_media_source = %d, media_source = %s\n", pcl_media_source,
2470               media_source);
2471
2472        if (pcl_media_source == -1)
2473          stp_deprintf(STP_DBG_PCL, "Unknown media source %s, ignored.\n", media_source);
2474        else if (pcl_media_source != PCL_PAPERSOURCE_STANDARD) {
2475
2476/* Correct the value by taking the modulus */
2477
2478	  if ((pcl_media_source & PAPERSOURCE_ADJ_GUIDE) ==
2479	      PAPERSOURCE_ADJ_GUIDE)
2480	    {
2481	      manual_feed_left_adjust = 1;
2482	      stp_deprintf(STP_DBG_PCL, "Adjusting left margin for manual feed.\n");
2483	    }
2484          pcl_media_source = pcl_media_source % PAPERSOURCE_MOD;
2485          stp_zprintf(v, "\033&l%dH", pcl_media_source);
2486        }
2487      }
2488
2489 /*
2490  * Convert media type string to the code, if specified.
2491  */
2492
2493      if (media_type && strlen(media_type) != 0) {
2494        pcl_media_type = pcl_string_to_val(media_type, pcl_media_types,
2495                           sizeof(pcl_media_types) / sizeof(pcl_t));
2496
2497        stp_deprintf(STP_DBG_PCL,"pcl_media_type = %d, media_type = %s\n", pcl_media_type,
2498               media_type);
2499
2500        if (pcl_media_type == -1) {
2501          stp_deprintf(STP_DBG_PCL, "Unknown media type %s, set to PLAIN.\n", media_type);
2502          pcl_media_type = PCL_PAPERTYPE_PLAIN;
2503        }
2504
2505/*
2506 * The HP812C doesn't like glossy paper being selected when using 600x600
2507 * C-RET (PhotoRET II). So we use Premium paper instead.
2508 *
2509 */
2510
2511        if (privdata.do_cretb && pcl_media_type == PCL_PAPERTYPE_GLOSSY) {
2512          stp_deprintf(STP_DBG_PCL, "Media type GLOSSY, set to PREMIUM for PhotoRET II.\n");
2513          pcl_media_type = PCL_PAPERTYPE_PREMIUM;
2514        }
2515      }
2516      else
2517        pcl_media_type = PCL_PAPERTYPE_PLAIN;
2518
2519 /*
2520  * Set DJ print quality to "best" if resolution >= 300
2521  */
2522
2523      if ((xdpi >= 300) && ((caps->stp_printer_type & PCL_PRINTER_DJ) == PCL_PRINTER_DJ))
2524      {
2525        if ((caps->stp_printer_type & PCL_PRINTER_MEDIATYPE) == PCL_PRINTER_MEDIATYPE)
2526        {
2527          stp_puts("\033*o1M", v);			/* Quality = presentation */
2528          stp_zprintf(v, "\033&l%dM", pcl_media_type);
2529        }
2530        else
2531        {
2532          stp_puts("\033*r2Q", v);			/* Quality (high) */
2533          stp_puts("\033*o2Q", v);			/* Shingling (4 passes) */
2534
2535 /* Depletion depends on media type and cart type. */
2536
2537          if ((pcl_media_type == PCL_PAPERTYPE_PLAIN)
2538           || (pcl_media_type == PCL_PAPERTYPE_BOND)) {
2539            if ((caps->color_type & PCL_COLOR_CMY) == PCL_COLOR_CMY)
2540              stp_puts("\033*o2D", v);			/* Depletion 25% */
2541            else
2542              stp_puts("\033*o5D", v);			/* Depletion 50% with gamma correction */
2543            }
2544
2545          else if ((pcl_media_type == PCL_PAPERTYPE_PREMIUM)
2546                 || (pcl_media_type == PCL_PAPERTYPE_GLOSSY)
2547                 || (pcl_media_type == PCL_PAPERTYPE_TRANS))
2548            stp_puts("\033*o1D", v);			/* Depletion none */
2549        }
2550      }
2551
2552/*
2553 * Duplex
2554 */
2555
2556      if (privdata.duplex)
2557          stp_zprintf(v,"\033&l%dS", privdata.duplex + privdata.tumble);
2558      }
2559    else
2560      {
2561        stp_deprintf(STP_DBG_PCL, "Back face init\n");
2562        stp_puts("\033&a2G", v);
2563      }
2564
2565/*
2566 * See if we need to use the CRD (Configure Raster Data) command, because we're
2567 * doing something interesting on a DeskJet.
2568 * (I hate long complicated if statements, the compiler will sort it out!).
2569 */
2570
2571  privdata.use_crd = 0;
2572  if ((caps->stp_printer_type & PCL_PRINTER_DJ) == PCL_PRINTER_DJ)
2573    {
2574    if (xdpi != ydpi)				/* Different X and Y Resolutions */
2575      privdata.use_crd = 1;
2576    if (privdata.do_cret)			/* Resolution Enhancement */
2577      privdata.use_crd = 1;
2578    if (privdata.do_6color)			/* Photo Ink printing */
2579      privdata.use_crd = 1;
2580    if (privdata.duplex)			/* Duplexing */
2581      privdata.use_crd = 1;
2582    }
2583
2584  if (privdata.use_crd)
2585						/* Set resolution using CRD */
2586  {
2587
2588/*
2589 * If duplexing on a CRD printer, we need to use the (re)load media command.
2590 */
2591
2592    if (privdata.duplex)
2593      stp_puts("\033&l-2H",v);			/* Load media */
2594
2595   /*
2596    * Send configure image data command with horizontal and
2597    * vertical resolutions as well as a color count...
2598    */
2599
2600    if (printing_color)
2601      if ((caps->color_type & PCL_COLOR_CMY) == PCL_COLOR_CMY)
2602        planes = 3;
2603      else
2604        if (privdata.do_6color)
2605          planes = 6;
2606        else
2607          planes = 4;
2608    else
2609      planes = 1;
2610
2611    stp_zprintf(v, "\033*g%dW", 2 + (planes * 6));
2612    stp_putc(2, v);				/* Format 2 (Complex Direct Planar) */
2613    stp_putc(planes, v);				/* # output planes */
2614
2615    if (planes != 3) {		/* Black resolution */
2616      stp_send_command(v, "", "HHH", xdpi, ydpi, (privdata.do_cretb || !privdata.do_cret) ? 2 : 4);
2617    }
2618
2619    if (planes != 1) {		/* Cyan, magenta, yellow resolutions */
2620      stp_send_command(v, "", "HHH", xdpi, ydpi, privdata.do_cret ? 4 : 2);
2621      stp_send_command(v, "", "HHH", xdpi, ydpi, privdata.do_cret ? 4 : 2);
2622      stp_send_command(v, "", "HHH", xdpi, ydpi, privdata.do_cret ? 4 : 2);
2623    }
2624    if (planes == 6)		/* LC, LM resolutions */
2625    {
2626      stp_send_command(v, "", "HHH", xdpi, ydpi, privdata.do_cret ? 4 : 2);
2627      stp_send_command(v, "", "HHH", xdpi, ydpi, privdata.do_cret ? 4 : 2);
2628    }
2629  }
2630  else
2631  {
2632    stp_zprintf(v, "\033*t%dR", xdpi);		/* Simple resolution */
2633    if (printing_color)
2634    {
2635      if ((caps->color_type & PCL_COLOR_CMY) == PCL_COLOR_CMY)
2636        stp_puts("\033*r-3U", v);		/* Simple CMY color */
2637      else
2638        stp_puts("\033*r-4U", v);		/* Simple KCMY color */
2639    }
2640  }
2641
2642  if ((caps->stp_printer_type & PCL_PRINTER_TIFF) == PCL_PRINTER_TIFF &&
2643      !(stp_get_debug_level() & STP_DBG_NO_COMPRESSION))
2644  {
2645    stp_puts("\033*b2M", v);			/* Mode 2 (TIFF) */
2646  }
2647  else
2648  {
2649    stp_puts("\033*b0M", v);			/* Mode 0 (no compression) */
2650  }
2651
2652 /*
2653  * Convert image size to printer resolution and setup the page for printing...
2654  */
2655
2656  out_width  = xdpi * out_width / 72;
2657  out_height = ydpi * out_height / 72;
2658
2659  if (pcl_media_size == PCL_PAPERSIZE_A4)
2660  {
2661    the_left_margin = caps->a4_margins.left_margin;
2662    the_top_margin = caps->a4_margins.top_margin;
2663  }
2664  else
2665  {
2666    the_left_margin = caps->normal_margins.left_margin;
2667    the_top_margin = caps->normal_margins.top_margin;
2668  }
2669
2670  stp_deprintf(STP_DBG_PCL, "left %d margin %d top %d margin %d width %d height %d\n",
2671	  left, the_left_margin, top, the_top_margin, out_width, out_height);
2672
2673  if (manual_feed_left_adjust)
2674    {
2675      unsigned wdelta = caps->custom_max_width - stp_get_page_width(v);
2676      if (wdelta > 0)
2677	{
2678	  /*
2679	   * Why 3?  I would expect it would be 2 here, but it appears
2680	   * that at least one printer (LJ 1022) actually partially
2681	   * adjusts the margin itself.  Adjusting the left margin by 1/3
2682	   * of the difference between the maximum width and the actual
2683	   * width experimentally yields correct results -- rlk 20081014
2684	   */
2685	  stp_deprintf(STP_DBG_PCL,
2686		       "  Adjusting manual feed left margin by %d\n", wdelta / 3);
2687	  extra_left_margin += wdelta / 3;
2688	}
2689    }
2690
2691  if (!privdata.do_cretb) {
2692    stp_zprintf(v, "\033&a%dH", 10 * (left + extra_left_margin));		/* Set left raster position */
2693    stp_zprintf(v, "\033&a%dV", 10 * (top + the_top_margin));
2694				/* Set top raster position */
2695  }
2696  stp_zprintf(v, "\033*r%dS", out_width);		/* Set raster width */
2697  stp_zprintf(v, "\033*r%dT", out_height);	/* Set raster height */
2698
2699  if (privdata.do_cretb)
2700    {
2701      /* Move to top left of printed area */
2702      stp_zprintf(v, "\033*p%dY", (top + the_top_margin)*4); /* Measured in dots. */
2703      stp_zprintf(v, "\033*p%dX", (left + extra_left_margin)*4);
2704    }
2705  stp_puts("\033*r1A", v); 			/* Start GFX */
2706
2707 /*
2708  * Allocate memory for the raster data...
2709  */
2710
2711  privdata.height = (out_width + 7) / 8;
2712  if (privdata.do_cret)
2713    privdata.height *= 2;
2714
2715  if (!printing_color)
2716  {
2717    black   = stp_malloc(privdata.height);
2718    cyan    = NULL;
2719    magenta = NULL;
2720    yellow  = NULL;
2721    lcyan    = NULL;
2722    lmagenta = NULL;
2723  }
2724  else
2725  {
2726    cyan    = stp_malloc(privdata.height);
2727    magenta = stp_malloc(privdata.height);
2728    yellow  = stp_malloc(privdata.height);
2729
2730    if ((caps->color_type & PCL_COLOR_CMY) == PCL_COLOR_CMY)
2731      black = NULL;
2732    else
2733      black = stp_malloc(privdata.height);
2734    if (privdata.do_6color)
2735    {
2736      lcyan    = stp_malloc(privdata.height);
2737      lmagenta = stp_malloc(privdata.height);
2738    }
2739    else
2740    {
2741      lcyan    = NULL;
2742      lmagenta = NULL;
2743    }
2744  }
2745
2746  if (black)
2747    {
2748      if (cyan)
2749	stp_set_string_parameter(v, "STPIOutputType", "KCMY");
2750      else
2751	stp_set_string_parameter(v, "STPIOutputType", "Grayscale");
2752    }
2753  else
2754    stp_set_string_parameter(v, "STPIOutputType", "CMY");
2755
2756/* Allocate buffer for pcl_mode2 tiff compression */
2757
2758  if ((caps->stp_printer_type & PCL_PRINTER_TIFF) == PCL_PRINTER_TIFF &&
2759      !(stp_get_debug_level() & STP_DBG_NO_COMPRESSION))
2760  {
2761    privdata.comp_buf = stp_malloc((privdata.height + 128 + 7) * 129 / 128);
2762    privdata.writefunc = pcl_mode2;
2763  }
2764  else
2765  {
2766    privdata.comp_buf = NULL;
2767    privdata.writefunc = pcl_mode0;
2768  }
2769
2770/* Set up dithering for special printers. */
2771
2772#if 1		/* Leave alone for now */
2773  if (!stp_check_float_parameter(v, "GCRLower", STP_PARAMETER_ACTIVE))
2774    stp_set_default_float_parameter(v, "GCRLower", .3);
2775  if (!stp_check_float_parameter(v, "GCRUpper", STP_PARAMETER_ACTIVE))
2776    stp_set_default_float_parameter(v, "GCRUpper", .999);
2777#endif
2778  stp_dither_init(v, image, out_width, xdpi, ydpi);
2779
2780  if (black)
2781    {
2782      stp_dither_add_channel(v, black, STP_ECOLOR_K, 0);
2783      stp_channel_set_black_channel(v, STP_ECOLOR_K);
2784    }
2785  if (cyan)
2786    stp_dither_add_channel(v, cyan, STP_ECOLOR_C, 0);
2787  if (lcyan)
2788    stp_dither_add_channel(v, lcyan, STP_ECOLOR_C, 1);
2789  if (magenta)
2790    stp_dither_add_channel(v, magenta, STP_ECOLOR_M, 0);
2791  if (lmagenta)
2792    stp_dither_add_channel(v, lmagenta, STP_ECOLOR_M, 1);
2793  if (yellow)
2794    stp_dither_add_channel(v, yellow, STP_ECOLOR_Y, 0);
2795
2796/* Ensure that density does not exceed 1.0 */
2797
2798  if (!stp_check_float_parameter(v, "Density", STP_PARAMETER_DEFAULTED))
2799    {
2800      stp_set_float_parameter_active(v, "Density", STP_PARAMETER_ACTIVE);
2801      stp_set_float_parameter(v, "Density", 1.0);
2802    }
2803
2804  stp_deprintf(STP_DBG_PCL, "Density: %f\n", stp_get_float_parameter(v, "Density"));
2805  if (stp_get_float_parameter(v, "Density") > 1.0)
2806    stp_set_float_parameter(v, "Density", 1.0);
2807  density = stp_get_float_parameter(v, "Density");
2808
2809  if (privdata.do_cret)			/* 4-level printing for 800/1120 */
2810    {
2811      if (yellow)
2812	stp_dither_set_inks_simple(v, STP_ECOLOR_Y, 3, dot_sizes_use, 1.0, 0.08);
2813      if (black && !privdata.do_cretb)
2814        stp_dither_set_inks_simple(v, STP_ECOLOR_K, 3, dot_sizes_use, 1.0, 1.0);
2815
2816      /* Note: no printer I know of does both CRet (4-level) and 6 colour, but
2817	 what the heck. variable_dither_ranges copied from print-escp2.c */
2818
2819      if (privdata.do_6color)			/* Photo for 69x */
2820	{
2821	  stp_dither_set_inks_full(v, STP_ECOLOR_C, 6, variable_shades, 1.0,
2822				    0.31 / .5);
2823	  stp_dither_set_inks_full(v, STP_ECOLOR_M, 6, variable_shades, 1.0,
2824				    0.61 / .97);
2825	}
2826      else
2827	{
2828	  if (cyan)
2829	    stp_dither_set_inks_simple(v, STP_ECOLOR_C, 3, dot_sizes_use, 1.0,
2830				       0.31 / .5);
2831	  if (magenta)
2832	    stp_dither_set_inks_simple(v, STP_ECOLOR_M, 3, dot_sizes_use, 1.0,
2833				       0.61 / .7);
2834	}
2835    }
2836  else if (privdata.do_6color)
2837    {
2838      /* Set light inks for 6 colour printers.
2839	 Numbers copied from print-escp2.c */
2840      stp_dither_set_inks_full(v, STP_ECOLOR_C, 2, photo_dither_shades, 1.0,
2841				0.31 / .5);
2842      stp_dither_set_inks_full(v, STP_ECOLOR_M, 2, photo_dither_shades, 1.0,
2843				0.61 / .7);
2844    }
2845  if (black)
2846    stp_channel_set_density_adjustment(v, STP_ECOLOR_K, 0,
2847				       get_double_param(v, "BlackDensity") *
2848				       get_double_param(v, "Density"));
2849  if (cyan)
2850    stp_channel_set_density_adjustment(v, STP_ECOLOR_C, 0,
2851				       get_double_param(v, "CyanDensity") *
2852				       get_double_param(v, "Density"));
2853  if (magenta)
2854    stp_channel_set_density_adjustment(v, STP_ECOLOR_M, 0,
2855				       get_double_param(v, "MagentaDensity") *
2856				       get_double_param(v, "Density"));
2857  if (yellow)
2858    stp_channel_set_density_adjustment(v, STP_ECOLOR_Y, 0,
2859					get_double_param(v, "YellowDensity") *
2860					get_double_param(v, "Density"));
2861  if (lcyan)
2862    stp_channel_set_density_adjustment
2863      (v, STP_ECOLOR_C, 1, (get_double_param(v, "CyanDensity") *
2864			get_double_param(v, "LightCyanTrans") *
2865			get_double_param(v, "Density")));
2866  if (lmagenta)
2867    stp_channel_set_density_adjustment
2868      (v, STP_ECOLOR_M, 1, (get_double_param(v, "MagentaDensity") *
2869			get_double_param(v, "LightMagentaTrans") *
2870			get_double_param(v, "Density")));
2871
2872
2873  if (!stp_check_curve_parameter(v, "HueMap", STP_PARAMETER_ACTIVE))
2874    {
2875      hue_adjustment = stp_curve_create_from_string(standard_hue_adjustment);
2876      stp_set_curve_parameter(v, "HueMap", hue_adjustment);
2877      stp_curve_destroy(hue_adjustment);
2878    }
2879  if (!stp_check_curve_parameter(v, "LumMap", STP_PARAMETER_ACTIVE))
2880    {
2881      lum_adjustment = stp_curve_create_from_string(standard_lum_adjustment);
2882      stp_curve_destroy(lum_adjustment);
2883    }
2884
2885  out_channels = stp_color_init(v, image, 65536);
2886
2887  errdiv  = image_height / out_height;
2888  errmod  = image_height % out_height;
2889  errval  = 0;
2890  errlast = -1;
2891  errline  = 0;
2892  privdata.blank_lines = 0;
2893#ifndef PCL_DEBUG_DISABLE_BLANKLINE_REMOVAL
2894  privdata.do_blank = ((caps->stp_printer_type & PCL_PRINTER_BLANKLINE) ==
2895		       PCL_PRINTER_BLANKLINE);
2896#else
2897  privdata.do_blank = 0;
2898#endif
2899  stp_allocate_component_data(v, "Driver", NULL, NULL, &privdata);
2900
2901  for (y = 0; y < out_height; y ++)
2902  {
2903    int duplicate_line = 1;
2904    if (errline != errlast)
2905    {
2906      errlast = errline;
2907      duplicate_line = 0;
2908      if (stp_color_get_row(v, image, errline, &zero_mask))
2909	{
2910	  status = 2;
2911	  break;
2912	}
2913    }
2914    stp_dither(v, y, duplicate_line, zero_mask, NULL);
2915    pcl_printfunc(v);
2916    stp_deprintf(STP_DBG_PCL,"pcl_print: y = %d, line = %d, val = %d, mod = %d, height = %d\n",
2917		  y, errline, errval, errmod, out_height);
2918    errval += errmod;
2919    errline += errdiv;
2920    if (errval >= out_height)
2921    {
2922      errval -= out_height;
2923      errline ++;
2924    }
2925  }
2926
2927/* Output trailing blank lines (may not be required?) */
2928
2929  if (privdata.blank_lines > 1)
2930  {
2931    privdata.blank_lines--;		/* correct for one already output */
2932    stp_deprintf(STP_DBG_PCL, "Blank Lines = %d\n", privdata.blank_lines);
2933    stp_zprintf(v, "\033*b%dY", privdata.blank_lines);
2934    privdata.blank_lines=0;
2935  }
2936
2937  stp_image_conclude(image);
2938
2939 /*
2940  * Cleanup...
2941  */
2942
2943  if (black != NULL)
2944    stp_free(black);
2945  if (cyan != NULL)
2946  {
2947    stp_free(cyan);
2948    stp_free(magenta);
2949    stp_free(yellow);
2950  }
2951  if (lcyan != NULL)
2952  {
2953    stp_free(lcyan);
2954    stp_free(lmagenta);
2955  }
2956
2957  if (privdata.comp_buf != NULL)
2958    stp_free(privdata.comp_buf);
2959
2960  if ((caps->stp_printer_type & PCL_PRINTER_NEW_ERG) == PCL_PRINTER_NEW_ERG)
2961    stp_puts("\033*rC", v);
2962  else
2963    stp_puts("\033*rB", v);
2964
2965  if ((privdata.duplex == 1) && ((page_number & 1) == 0))
2966      stp_puts("\014", v);		/* Form feed */
2967  else
2968    {
2969      stp_puts("\033&l0H", v);		/* Eject page */
2970      if (privdata.do_cretb)
2971        stp_zprintf(v, "\033%%-12345X\n");
2972      stp_puts("\033E", v); 		/* PCL reset */
2973    }
2974  return status;
2975}
2976
2977static int
2978pcl_print(const stp_vars_t *v, stp_image_t *image)
2979{
2980  int status;
2981  stp_vars_t *nv = stp_vars_create_copy(v);
2982  stp_prune_inactive_options(nv);
2983  status = pcl_do_print(nv, image);
2984  stp_vars_destroy(nv);
2985  return status;
2986}
2987
2988static const stp_printfuncs_t print_pcl_printfuncs =
2989{
2990  pcl_list_parameters,
2991  pcl_parameters,
2992  stp_default_media_size,
2993  pcl_imageable_area,
2994  pcl_imageable_area,
2995  pcl_limit,
2996  pcl_print,
2997  pcl_describe_resolution,
2998  pcl_describe_output,
2999  stp_verify_printer_params,
3000  NULL,
3001  NULL,
3002  NULL
3003};
3004
3005
3006/*
3007 * 'pcl_mode0()' - Send PCL graphics using mode 0 (no) compression.
3008 */
3009
3010static void
3011pcl_mode0(stp_vars_t *v,		/* I - Print file or command */
3012          unsigned char *line,		/* I - Output bitmap data */
3013          int           height,		/* I - Height of bitmap data */
3014          int           last_plane)	/* I - True if this is the last plane */
3015{
3016  stp_zprintf(v, "\033*b%d%c", height, last_plane ? 'W' : 'V');
3017  stp_zfwrite((const char *) line, height, 1, v);
3018}
3019
3020
3021/*
3022 * 'pcl_mode2()' - Send PCL graphics using mode 2 (TIFF) compression.
3023 */
3024
3025static void
3026pcl_mode2(stp_vars_t *v,		/* I - Print file or command */
3027          unsigned char *line,		/* I - Output bitmap data */
3028          int           height,		/* I - Height of bitmap data */
3029          int           last_plane)	/* I - True if this is the last plane */
3030{
3031  pcl_privdata_t *privdata =
3032    (pcl_privdata_t *) stp_get_component_data(v, "Driver");
3033  unsigned char *comp_buf = privdata->comp_buf;
3034  unsigned char	*comp_ptr;		/* Current slot in buffer */
3035
3036  stp_pack_tiff(v, line, height, comp_buf, &comp_ptr, NULL, NULL);
3037
3038 /*
3039  * Send a line of raster graphics...
3040  */
3041
3042  stp_zprintf(v, "\033*b%d%c", (int)(comp_ptr - comp_buf), last_plane ? 'W' : 'V');
3043  stp_zfwrite((const char *)comp_buf, comp_ptr - comp_buf, 1, v);
3044}
3045
3046
3047static stp_family_t print_pcl_module_data =
3048  {
3049    &print_pcl_printfuncs,
3050    NULL
3051  };
3052
3053
3054static int
3055print_pcl_module_init(void)
3056{
3057  return stp_family_register(print_pcl_module_data.printer_list);
3058}
3059
3060
3061static int
3062print_pcl_module_exit(void)
3063{
3064  return stp_family_unregister(print_pcl_module_data.printer_list);
3065}
3066
3067
3068/* Module header */
3069#define stp_module_version print_pcl_LTX_stp_module_version
3070#define stp_module_data print_pcl_LTX_stp_module_data
3071
3072stp_module_version_t stp_module_version = {0, 0};
3073
3074stp_module_t stp_module_data =
3075  {
3076    "pcl",
3077    VERSION,
3078    "PCL family driver",
3079    STP_MODULE_CLASS_FAMILY,
3080    NULL,
3081    print_pcl_module_init,
3082    print_pcl_module_exit,
3083    (void *) &print_pcl_module_data
3084  };
3085
3086