libgimpprint API Reference: src/main/print-pcl.c Source File

Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

# src/main/print-pcl.c

Go to the documentation of this file.

    00001 /*
    00002  * "$Id: print-pcl_8c-source.html,v 1.1.1.2 2004/12/22 23:49:09 jlovell Exp $"
    00003  *
    00004  *   Print plug-in HP PCL driver for the GIMP.
    00005  *
    00006  *   Copyright 1997-2000 Michael Sweet (mike@easysw.com),
    00007  *      Robert Krawitz (rlk@alum.mit.edu) and
    00008  *      Dave Hill (dave@minnie.demon.co.uk)
    00009  *
    00010  *   This program is free software; you can redistribute it and/or modify it
    00011  *   under the terms of the GNU General Public License as published by the Free
    00012  *   Software Foundation; either version 2 of the License, or (at your option)
    00013  *   any later version.
    00014  *
    00015  *   This program is distributed in the hope that it will be useful, but
    00016  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    00017  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    00018  *   for more details.
    00019  *
    00020  *   You should have received a copy of the GNU General Public License
    00021  *   along with this program; if not, write to the Free Software
    00022  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    00023  */
    00024
    00025 /*
    00026  * This file must include only standard C header files.  The core code must
    00027  * compile on generic platforms that don't support glib, gimp, gtk, etc.
    00028  */
    00029
    00030 #ifdef HAVE_CONFIG_H
    00031 #include <config.h>
    00032 #endif
    00033 #include <gimp-print/gimp-print.h>
    00034 #include <gimp-print/gimp-print-intl-internal.h>
    00035 #include "gimp-print-internal.h"
    00036 #include <stdio.h>
    00037 #include <string.h>
    00038
    00039 /* #define DEBUG */
    00040 /* #define PCL_DEBUG_DISABLE_COMPRESSION */
    00041 /* #define PCL_DEBUG_DISABLE_BLANKLINE_REMOVAL */
    00042
    00043 /*
    00044  * Local functions...
    00045  */
    00046 static void     pcl_mode0(stp_vars_t *, unsigned char *, int, int);
    00047 static void     pcl_mode2(stp_vars_t *, unsigned char *, int, int);
    00048 #define MAX(a, b) ((a) > (b) ? (a) : (b))
    00049
    00050 typedef struct
    00051 {
    00052   int do_blank;
    00053   int blank_lines;
    00054   unsigned char *comp_buf;
    00055   void (*writefunc)(stp_vars_t *, unsigned char *, int, int);   /* PCL output function */
    00056   int do_cret;
    00057   int do_cretb;
    00058   int do_6color;
    00059   int height;
    00060   int duplex;
    00061   int tumble;
    00062   int use_crd;
    00063 } pcl_privdata_t;
    00064
    00065 /*
    00066  * Generic define for a name/value set
    00067  */
    00068
    00069 typedef struct
    00070 {
    00071   const char    *pcl_name;
    00072   const char    *pcl_text;
    00073   int           pcl_code;
    00074   int           p0;
    00075   int           p1;
    00076 } pcl_t;
    00077
    00078 static const stp_dotsize_t single_dotsize[] =
    00079 {
    00080   { 0x1, 1.0 }
    00081 };
    00082
    00083 static const stp_shade_t photo_dither_shades[] =
    00084 {
    00085   { 1.0000, 1, single_dotsize },
    00086   { 0.3333, 1, single_dotsize },
    00087 };
    00088
    00089 /*
    00090  * Media size to PCL media size code table
    00091  *
    00092  * Note, you can force the list of papersizes given in the GUI to be only those
    00093  * supported by defining PCL_NO_CUSTOM_PAPERSIZES
    00094  */
    00095
    00096 /* #define PCL_NO_CUSTOM_PAPERSIZES */
    00097
    00098 #define PCL_PAPERSIZE_EXECUTIVE         1
    00099 #define PCL_PAPERSIZE_LETTER            2
    00100 #define PCL_PAPERSIZE_LEGAL             3
    00101 #define PCL_PAPERSIZE_TABLOID           6       /* "Ledger" */
    00102 #define PCL_PAPERSIZE_STATEMENT         15      /* Called "Manual" in print-util */
    00103 #define PCL_PAPERSIZE_SUPER_B           16      /* Called "13x19" in print-util */
    00104 #define PCL_PAPERSIZE_A5                25
    00105 #define PCL_PAPERSIZE_A4                26
    00106 #define PCL_PAPERSIZE_A3                27
    00107 #define PCL_PAPERSIZE_JIS_B5            45
    00108 #define PCL_PAPERSIZE_JIS_B4            46
    00109 #define PCL_PAPERSIZE_HAGAKI_CARD       71
    00110 #define PCL_PAPERSIZE_OUFUKU_CARD       72
    00111 #define PCL_PAPERSIZE_A6_CARD           73
    00112 #define PCL_PAPERSIZE_4x6               74
    00113 #define PCL_PAPERSIZE_5x8               75
    00114 #define PCL_PAPERSIZE_3x5               78
    00115 #define PCL_PAPERSIZE_MONARCH_ENV       80
    00116 #define PCL_PAPERSIZE_COMMERCIAL10_ENV  81
    00117 #define PCL_PAPERSIZE_DL_ENV            90
    00118 #define PCL_PAPERSIZE_C5_ENV            91
    00119 #define PCL_PAPERSIZE_C6_ENV            92
    00120 #define PCL_PAPERSIZE_CUSTOM            101     /* Custom size */
    00121 #define PCL_PAPERSIZE_INVITATION_ENV    109
    00122 #define PCL_PAPERSIZE_JAPANESE_3_ENV    110
    00123 #define PCL_PAPERSIZE_JAPANESE_4_ENV    111
    00124 #define PCL_PAPERSIZE_KAKU_ENV          113
    00125 #define PCL_PAPERSIZE_HP_CARD           114     /* HP Greeting card!?? */
    00126
    00127 /*
    00128  * This data comes from the HP documentation "Deskjet 1220C and 1120C
    00129  * PCL reference guide 2.0, Nov 1999". NOTE: The first name *must* match
    00130  * those in print-util.c for the lookups to work properly!
    00131  * The long names are not used so they have been removed, the ones in
    00132  * print-util.c are used in the interface.
    00133  */
    00134
    00135 static const pcl_t pcl_media_sizes[] =
    00136 {
    00137     { "Executive", "notused", PCL_PAPERSIZE_EXECUTIVE},                 /* US Exec (7.25 x 10.5 in) */
    00138     { "Letter", "notused", PCL_PAPERSIZE_LETTER},                       /* US Letter (8.5 x 11 in) */
    00139     { "Legal", "notused", PCL_PAPERSIZE_LEGAL},                         /* US Legal (8.5 x 14 in) */
    00140     { "Tabloid", "notused", PCL_PAPERSIZE_TABLOID},                     /* US Tabloid (11 x 17 in) */
    00141     { "Statement", "notused", PCL_PAPERSIZE_STATEMENT},                 /* US Manual/Statement (5.5 x 8.5 in) */
    00142     { "SuperB", "notused", PCL_PAPERSIZE_SUPER_B},                      /* US 13x19/Super B (13 x 19 in) */
    00143     { "A5", "notused", PCL_PAPERSIZE_A5},                               /* ISO/JIS A5 (148 x 210 mm) */
    00144     { "A4", "notused", PCL_PAPERSIZE_A4},                               /* ISO/JIS A4 (210 x 297 mm) */
    00145     { "A3", "notused", PCL_PAPERSIZE_A3},                               /* ISO/JIS A3 (297 x 420 mm) */
    00146     { "B5", "notused", PCL_PAPERSIZE_JIS_B5},                           /* JIS B5 (182 x 257 mm). */
    00147     { "B4", "notused", PCL_PAPERSIZE_JIS_B4},                           /* JIS B4 (257 x 364 mm). */
    00148     { "w283h420", "notused", PCL_PAPERSIZE_HAGAKI_CARD},                /* Japanese Hagaki Card (100 x 148 mm) */
    00149     { "w420h567", "notused", PCL_PAPERSIZE_OUFUKU_CARD},                /* Japanese Oufuku Card (148 x 200 mm) */
    00150     { "A6", "notused", PCL_PAPERSIZE_A6_CARD},                          /* ISO/JIS A6 card */
    00151     { "w288h432", "notused", PCL_PAPERSIZE_4x6},                        /* US Index card (4 x 6 in) */
    00152     { "w360h576", "notused", PCL_PAPERSIZE_5x8},                        /* US Index card (5 x 8 in) */
    00153     { "w216h360", "notused", PCL_PAPERSIZE_3x5},                        /* US Index card (3 x 5 in) */
    00154     { "Monarch", "notused", PCL_PAPERSIZE_MONARCH_ENV},                 /* Monarch Envelope (3 7/8 x 7 1/2 in) */
    00155     { "COM10", "notused", PCL_PAPERSIZE_COMMERCIAL10_ENV},              /* US Commercial 10 Envelope (4.125 x 9.5 in) Portrait */
    00156     { "DL", "notused", PCL_PAPERSIZE_DL_ENV},                           /* DL envelope (110 x 220 mm) Portrait */
    00157     { "C5", "notused", PCL_PAPERSIZE_C5_ENV},                           /* C5 envelope (162 x 229 mm) */
    00158     { "C6", "notused", PCL_PAPERSIZE_C6_ENV},                           /* C6 envelope (114 x 162 mm) */
    00159     { "w315h414", "notused", PCL_PAPERSIZE_INVITATION_ENV},             /* US A2 Invitation envelope (4 3/8 x 5 3/4 in) */
    00160     { "w340h666", "notused", PCL_PAPERSIZE_JAPANESE_3_ENV},             /* Japanese Long Envelope #3 (120 x 235 mm) */
    00161     { "w255h581", "notused", PCL_PAPERSIZE_JAPANESE_4_ENV},             /* Japanese Long Envelope #4 (90 x 205 mm) */
    00162     { "w680h941", "notused", PCL_PAPERSIZE_KAKU_ENV},                   /* Japanese Kaku Envelope (240 x 332.1 mm) */
    00163 /**** MRS: this size not supported by print-util funcs! ****/
    00164     { "w612h792", "notused", PCL_PAPERSIZE_HP_CARD},                    /* Hp greeting card */
    00165 };
    00166 #define NUM_PRINTER_PAPER_SIZES (sizeof(pcl_media_sizes) / sizeof(pcl_t))
    00167
    00168 /*
    00169  * Media type to code table
    00170  */
    00171
    00172 #define PCL_PAPERTYPE_PLAIN     0
    00173 #define PCL_PAPERTYPE_BOND      1
    00174 #define PCL_PAPERTYPE_PREMIUM   2
    00175 #define PCL_PAPERTYPE_GLOSSY    3       /* or photo */
    00176 #define PCL_PAPERTYPE_TRANS     4
    00177 #define PCL_PAPERTYPE_QPHOTO    5       /* Quick dry photo (2000 only) */
    00178 #define PCL_PAPERTYPE_QTRANS    6       /* Quick dry transparency (2000 only) */
    00179
    00180 static const pcl_t pcl_media_types[] =
    00181 {
    00182     { "Plain", N_ ("Plain"), PCL_PAPERTYPE_PLAIN},
    00183     { "Bond", N_ ("Bond"), PCL_PAPERTYPE_BOND},
    00184     { "Premium", N_ ("Premium"), PCL_PAPERTYPE_PREMIUM},
    00185     { "Glossy", N_ ("Glossy Photo"), PCL_PAPERTYPE_GLOSSY},
    00186     { "Transparency", N_ ("Transparency"), PCL_PAPERTYPE_TRANS},
    00187     { "GlossyQD", N_ ("Quick-dry Photo"), PCL_PAPERTYPE_QPHOTO},
    00188     { "TransparencyQD", N_ ("Quick-dry Transparency"), PCL_PAPERTYPE_QTRANS},
    00189 };
    00190 #define NUM_PRINTER_PAPER_TYPES (sizeof(pcl_media_types) / sizeof(pcl_t))
    00191
    00192 /*
    00193  * Media feed to code table. There are different names for the same code,
    00194  * so we encode them by adding "lumps" of "PAPERSOURCE_MOD".
    00195  * This is removed later to get back to the main codes.
    00196  */
    00197
    00198 #define PAPERSOURCE_MOD                 16
    00199
    00200 #define PCL_PAPERSOURCE_STANDARD        0       /* Don't output code */
    00201 #define PCL_PAPERSOURCE_MANUAL          2
    00202 #define PCL_PAPERSOURCE_ENVELOPE        3       /* Not used */
    00203
    00204 /* LaserJet types */
    00205 #define PCL_PAPERSOURCE_LJ_TRAY2        1
    00206 #define PCL_PAPERSOURCE_LJ_TRAY3        4
    00207 #define PCL_PAPERSOURCE_LJ_TRAY4        5
    00208 #define PCL_PAPERSOURCE_LJ_TRAY1        8
    00209
    00210 /* Deskjet 340 types */
    00211 #define PCL_PAPERSOURCE_340_PCSF        1 + PAPERSOURCE_MOD
    00212                                                 /* Portable sheet feeder for 340 */
    00213 #define PCL_PAPERSOURCE_340_DCSF        4 + PAPERSOURCE_MOD
    00214                                                 /* Desktop sheet feeder for 340 */
    00215
    00216 /* Other Deskjet types */
    00217 #define PCL_PAPERSOURCE_DJ_TRAY         1 + PAPERSOURCE_MOD + PAPERSOURCE_MOD
    00218 #define PCL_PAPERSOURCE_DJ_TRAY2        4 + PAPERSOURCE_MOD + PAPERSOURCE_MOD
    00219                                                 /* Tray 2 for 2500 */
    00220 #define PCL_PAPERSOURCE_DJ_OPTIONAL     5 + PAPERSOURCE_MOD + PAPERSOURCE_MOD
    00221                                                 /* Optional source for 2500 */
    00222 #define PCL_PAPERSOURCE_DJ_AUTO         7 + PAPERSOURCE_MOD + PAPERSOURCE_MOD
    00223                                                 /* Autoselect for 2500 */
    00224
    00225 static const pcl_t pcl_media_sources[] =
    00226 {
    00227     { "Standard", N_ ("Standard"), PCL_PAPERSOURCE_STANDARD},
    00228     { "Manual", N_ ("Manual"), PCL_PAPERSOURCE_MANUAL},
    00229 /*  {"Envelope", PCL_PAPERSOURCE_ENVELOPE}, */
    00230     { "MultiPurpose", N_ ("Tray 1"), PCL_PAPERSOURCE_LJ_TRAY1},
    00231     { "Upper", N_ ("Tray 2"), PCL_PAPERSOURCE_LJ_TRAY2},
    00232     { "Lower", N_ ("Tray 3"), PCL_PAPERSOURCE_LJ_TRAY3},
    00233     { "LargeCapacity", N_ ("Tray 4"), PCL_PAPERSOURCE_LJ_TRAY4},
    00234     { "Portable", N_ ("Portable Sheet Feeder"), PCL_PAPERSOURCE_340_PCSF},
    00235     { "Desktop", N_ ("Desktop Sheet Feeder"), PCL_PAPERSOURCE_340_DCSF},
    00236     { "Tray", N_ ("Tray"), PCL_PAPERSOURCE_DJ_TRAY},
    00237     { "Tray2", N_ ("Tray 2"), PCL_PAPERSOURCE_DJ_TRAY2},
    00238     { "Optional", N_ ("Optional Source"), PCL_PAPERSOURCE_DJ_OPTIONAL},
    00239     { "Auto", N_ ("Autoselect"), PCL_PAPERSOURCE_DJ_AUTO},
    00240 };
    00241 #define NUM_PRINTER_PAPER_SOURCES       (sizeof(pcl_media_sources) / sizeof(pcl_t))
    00242
    00243 #define PCL_RES_150_150         1
    00244 #define PCL_RES_300_300         2
    00245 #define PCL_RES_600_300         4       /* DJ 600 series */
    00246 #define PCL_RES_600_600_MONO    8       /* DJ 600/800/1100/2000 b/w only */
    00247 #define PCL_RES_600_600         16      /* DJ 9xx/1220C/PhotoSmart */
    00248 #define PCL_RES_1200_600        32      /* DJ 9xx/1220C/PhotoSmart */
    00249 #define PCL_RES_2400_600        64      /* DJ 9xx/1220C/PhotoSmart */
    00250
    00251 static const pcl_t pcl_resolutions[] =
    00252 {
    00253     { "150dpi", N_("150x150 DPI"), PCL_RES_150_150, 150, 150},
    00254     { "300dpi", N_("300x300 DPI"), PCL_RES_300_300, 300, 300},
    00255     { "600x300dpi", N_("600x300 DPI"), PCL_RES_600_300, 600, 300},
    00256     { "600mono", N_("600x600 DPI monochrome"), PCL_RES_600_600_MONO, 600, 600},
    00257     { "600dpi", N_("600x600 DPI"), PCL_RES_600_600, 600, 600},
    00258     { "1200x600dpi", N_("1200x600 DPI"), PCL_RES_1200_600, 1200, 600},
    00259     { "2400x600dpi", N_("2400x600 DPI"), PCL_RES_2400_600, 2400, 600},
    00260 };
    00261 #define NUM_RESOLUTIONS         (sizeof(pcl_resolutions) / sizeof (pcl_t))
    00262
    00263 static void
    00264 pcl_describe_resolution(const stp_vars_t *v, int *x, int *y)
    00265 {
    00266   int i;
    00267   const char *resolution = stp_get_string_parameter(v, "Resolution");
    00268   if (resolution)
    00269     {
    00270       for (i = 0; i < NUM_RESOLUTIONS; i++)
    00271         {
    00272           if (!strcmp(resolution, pcl_resolutions[i].pcl_name))
    00273             {
    00274               *x = pcl_resolutions[i].p0;
    00275               *y = pcl_resolutions[i].p1;
    00276               return;
    00277             }
    00278         }
    00279     }
    00280   *x = -1;
    00281   *y = -1;
    00282 }
    00283
    00284 typedef struct {
    00285   int top_margin;
    00286   int bottom_margin;
    00287   int left_margin;
    00288   int right_margin;
    00289 } margins_t;
    00290
    00291 /*
    00292  * Printer capability data
    00293  */
    00294
    00295 typedef struct {
    00296   int model;
    00297   int custom_max_width;
    00298   int custom_max_height;
    00299   int custom_min_width;
    00300   int custom_min_height;
    00301   int resolutions;
    00302   margins_t normal_margins;
    00303   margins_t a4_margins;
    00304   int color_type;               /* 2 print head or one, 2 level or 4 */
    00305   int stp_printer_type;         /* Deskjet/Laserjet and quirks */
    00306 /* The paper size, paper type and paper source codes cannot be combined */
    00307   const short *paper_sizes;     /* Paper sizes */
    00308   const short *paper_types;     /* Paper types */
    00309   const short *paper_sources;   /* Paper sources */
    00310   } pcl_cap_t;
    00311
    00312 #define PCL_COLOR_NONE          0
    00313 #define PCL_COLOR_CMY           1       /* One print head */
    00314 #define PCL_COLOR_CMYK          2       /* Two print heads */
    00315 #define PCL_COLOR_CMYK4         4       /* CRet printing */
    00316 #define PCL_COLOR_CMYKcm        8       /* CMY + Photo Cart */
    00317 #define PCL_COLOR_CMYK4b        16      /* CRet for HP840c */
    00318
    00319 #define PCL_PRINTER_LJ          1
    00320 #define PCL_PRINTER_DJ          2
    00321 #define PCL_PRINTER_NEW_ERG     4       /* use "\033*rC" to end raster graphics,
    00322                                            instead of "\033*rB" */
    00323 #define PCL_PRINTER_TIFF        8       /* Use TIFF compression */
    00324 #define PCL_PRINTER_MEDIATYPE   16      /* Use media type & print quality */
    00325 #define PCL_PRINTER_CUSTOM_SIZE 32      /* Custom sizes supported */
    00326 #define PCL_PRINTER_BLANKLINE   64      /* Blank line removal supported */
    00327 #define PCL_PRINTER_DUPLEX      128     /* Printer can have duplexer */
    00328
    00329 /*
    00330  * FIXME - the 520 shouldn't be lumped in with the 500 as it supports
    00331  * more paper sizes.
    00332  *
    00333  * The following models use depletion, raster quality and shingling:-
    00334  * 500, 500c, 510, 520, 550c, 560c.
    00335  * The rest use Media Type and Print Quality.
    00336  *
    00337  * This data comes from the HP documentation "Deskjet 1220C and 1120C
    00338  * PCL reference guide 2.0, Nov 1999".
    00339  */
    00340
    00341 static const short emptylist[] =
    00342 {
    00343   -1
    00344 };
    00345
    00346 static const short standard_papersizes[] =
    00347 {
    00348   PCL_PAPERSIZE_EXECUTIVE,
    00349   PCL_PAPERSIZE_STATEMENT,
    00350   PCL_PAPERSIZE_LETTER,
    00351   PCL_PAPERSIZE_LEGAL,
    00352   PCL_PAPERSIZE_A4,
    00353   -1,
    00354 };
    00355
    00356 static const short letter_only_papersizes[] =
    00357 {
    00358   PCL_PAPERSIZE_LETTER,
    00359   -1
    00360 };
    00361
    00362 static const short dj340_papersizes[] =
    00363 {
    00364   PCL_PAPERSIZE_EXECUTIVE,
    00365   PCL_PAPERSIZE_LETTER,
    00366   PCL_PAPERSIZE_LEGAL,
    00367   PCL_PAPERSIZE_A4,
    00368   -1,
    00369 };
    00370
    00371 static const short dj400_papersizes[] =
    00372 {
    00373   PCL_PAPERSIZE_EXECUTIVE,
    00374   PCL_PAPERSIZE_LETTER,
    00375   PCL_PAPERSIZE_LEGAL,
    00376   PCL_PAPERSIZE_A4,
    00377   PCL_PAPERSIZE_JIS_B5,
    00378   -1,
    00379 };
    00380
    00381 static const short dj500_papersizes[] =
    00382 {
    00383 /*    PCL_PAPERSIZE_EXECUTIVE, The 500 doesn't support this, the 520 does */
    00384   PCL_PAPERSIZE_LETTER,
    00385   PCL_PAPERSIZE_LEGAL,
    00386   PCL_PAPERSIZE_A4,
    00387   PCL_PAPERSIZE_COMMERCIAL10_ENV,
    00388 /*    PCL_PAPERSIZE_DL_ENV,    The 500 doesn't support this, the 520 does */
    00389   -1,
    00390 };
    00391
    00392 static const short dj540_papersizes[] =
    00393 {
    00394   PCL_PAPERSIZE_EXECUTIVE,
    00395   PCL_PAPERSIZE_LETTER,
    00396   PCL_PAPERSIZE_LEGAL,
    00397   PCL_PAPERSIZE_A4,
    00398   PCL_PAPERSIZE_A5,
    00399   PCL_PAPERSIZE_JIS_B5,
    00400   PCL_PAPERSIZE_HAGAKI_CARD,
    00401   PCL_PAPERSIZE_A6_CARD,
    00402   PCL_PAPERSIZE_4x6,
    00403   PCL_PAPERSIZE_5x8,
    00404   PCL_PAPERSIZE_COMMERCIAL10_ENV,
    00405   PCL_PAPERSIZE_DL_ENV,
    00406   PCL_PAPERSIZE_C6_ENV,
    00407   -1,
    00408 };
    00409
    00410 static const short dj600_papersizes[] =
    00411 {
    00412   PCL_PAPERSIZE_EXECUTIVE,
    00413   PCL_PAPERSIZE_LETTER,
    00414   PCL_PAPERSIZE_LEGAL,
    00415   PCL_PAPERSIZE_A4,
    00416   PCL_PAPERSIZE_A5,
    00417   PCL_PAPERSIZE_HAGAKI_CARD,
    00418   PCL_PAPERSIZE_A6_CARD,
    00419   PCL_PAPERSIZE_4x6,
    00420   PCL_PAPERSIZE_5x8,
    00421   PCL_PAPERSIZE_COMMERCIAL10_ENV,
    00422   PCL_PAPERSIZE_DL_ENV,
    00423   PCL_PAPERSIZE_C6_ENV,
    00424   PCL_PAPERSIZE_INVITATION_ENV,
    00425   -1,
    00426 };
    00427
    00428 static const short dj1220_papersizes[] =
    00429 {
    00430   PCL_PAPERSIZE_EXECUTIVE,
    00431   PCL_PAPERSIZE_LETTER,
    00432   PCL_PAPERSIZE_LEGAL,
    00433   PCL_PAPERSIZE_TABLOID,
    00434   PCL_PAPERSIZE_STATEMENT,
    00435   PCL_PAPERSIZE_SUPER_B,
    00436   PCL_PAPERSIZE_A5,
    00437   PCL_PAPERSIZE_A4,
    00438   PCL_PAPERSIZE_A3,
    00439   PCL_PAPERSIZE_JIS_B5,
    00440   PCL_PAPERSIZE_JIS_B4,
    00441   PCL_PAPERSIZE_HAGAKI_CARD,
    00442   PCL_PAPERSIZE_OUFUKU_CARD,
    00443   PCL_PAPERSIZE_A6_CARD,
    00444   PCL_PAPERSIZE_4x6,
    00445   PCL_PAPERSIZE_5x8,
    00446   PCL_PAPERSIZE_3x5,
    00447   PCL_PAPERSIZE_HP_CARD,
    00448   PCL_PAPERSIZE_MONARCH_ENV,
    00449   PCL_PAPERSIZE_COMMERCIAL10_ENV,
    00450   PCL_PAPERSIZE_DL_ENV,
    00451   PCL_PAPERSIZE_C5_ENV,
    00452   PCL_PAPERSIZE_C6_ENV,
    00453   PCL_PAPERSIZE_INVITATION_ENV,
    00454   PCL_PAPERSIZE_JAPANESE_3_ENV,
    00455   PCL_PAPERSIZE_JAPANESE_4_ENV,
    00456   PCL_PAPERSIZE_KAKU_ENV,
    00457   -1,
    00458 };
    00459
    00460 static const short dj1100_papersizes[] =
    00461 {
    00462   PCL_PAPERSIZE_EXECUTIVE,
    00463   PCL_PAPERSIZE_LETTER,
    00464   PCL_PAPERSIZE_LEGAL,
    00465   PCL_PAPERSIZE_TABLOID,
    00466   PCL_PAPERSIZE_STATEMENT,
    00467   PCL_PAPERSIZE_SUPER_B,
    00468   PCL_PAPERSIZE_A5,
    00469   PCL_PAPERSIZE_A4,
    00470   PCL_PAPERSIZE_A3,
    00471   PCL_PAPERSIZE_JIS_B5,
    00472   PCL_PAPERSIZE_JIS_B4,
    00473   PCL_PAPERSIZE_HAGAKI_CARD,
    00474   PCL_PAPERSIZE_A6_CARD,
    00475   PCL_PAPERSIZE_4x6,
    00476   PCL_PAPERSIZE_5x8,
    00477   PCL_PAPERSIZE_COMMERCIAL10_ENV,
    00478   PCL_PAPERSIZE_DL_ENV,
    00479   PCL_PAPERSIZE_C6_ENV,
    00480   PCL_PAPERSIZE_INVITATION_ENV,
    00481   PCL_PAPERSIZE_JAPANESE_3_ENV,
    00482   PCL_PAPERSIZE_JAPANESE_4_ENV,
    00483   PCL_PAPERSIZE_KAKU_ENV,
    00484   -1,
    00485 };
    00486
    00487 static const short dj1200_papersizes[] =
    00488 {
    00489   /* This printer is not mentioned in the Comparison tables,
    00490      so I'll just pick some likely sizes... */
    00491   PCL_PAPERSIZE_EXECUTIVE,
    00492   PCL_PAPERSIZE_LETTER,
    00493   PCL_PAPERSIZE_LEGAL,
    00494   PCL_PAPERSIZE_A5,
    00495   PCL_PAPERSIZE_A4,
    00496   PCL_PAPERSIZE_4x6,
    00497   PCL_PAPERSIZE_5x8,
    00498   -1,
    00499 };
    00500
    00501 static const short dj2000_papersizes[] =
    00502 {
    00503   PCL_PAPERSIZE_EXECUTIVE,
    00504   PCL_PAPERSIZE_LETTER,
    00505   PCL_PAPERSIZE_LEGAL,
    00506   PCL_PAPERSIZE_A5,
    00507   PCL_PAPERSIZE_A4,
    00508   PCL_PAPERSIZE_HAGAKI_CARD,
    00509   PCL_PAPERSIZE_A6_CARD,
    00510   PCL_PAPERSIZE_4x6,
    00511   PCL_PAPERSIZE_5x8,
    00512   PCL_PAPERSIZE_3x5,
    00513   PCL_PAPERSIZE_COMMERCIAL10_ENV,
    00514   PCL_PAPERSIZE_DL_ENV,
    00515   PCL_PAPERSIZE_C6_ENV,
    00516   PCL_PAPERSIZE_INVITATION_ENV,
    00517   -1,
    00518 };
    00519
    00520 static const short dj2500_papersizes[] =
    00521 {
    00522   PCL_PAPERSIZE_EXECUTIVE,
    00523   PCL_PAPERSIZE_LETTER,
    00524   PCL_PAPERSIZE_LEGAL,
    00525   PCL_PAPERSIZE_TABLOID,
    00526   PCL_PAPERSIZE_STATEMENT,
    00527   PCL_PAPERSIZE_A5,
    00528   PCL_PAPERSIZE_A4,
    00529   PCL_PAPERSIZE_A3,
    00530   PCL_PAPERSIZE_JIS_B5,
    00531   PCL_PAPERSIZE_JIS_B4,
    00532   PCL_PAPERSIZE_HAGAKI_CARD,
    00533   PCL_PAPERSIZE_A6_CARD,
    00534   PCL_PAPERSIZE_4x6,
    00535   PCL_PAPERSIZE_5x8,
    00536   PCL_PAPERSIZE_COMMERCIAL10_ENV,
    00537   PCL_PAPERSIZE_DL_ENV,
    00538   -1,
    00539 };
    00540
    00541 static const short ljsmall_papersizes[] =
    00542 {
    00543   PCL_PAPERSIZE_EXECUTIVE,
    00544   PCL_PAPERSIZE_STATEMENT,
    00545   PCL_PAPERSIZE_LETTER,
    00546   PCL_PAPERSIZE_LEGAL,
    00547   PCL_PAPERSIZE_A4,
    00548   PCL_PAPERSIZE_MONARCH_ENV,
    00549   PCL_PAPERSIZE_COMMERCIAL10_ENV,
    00550   PCL_PAPERSIZE_DL_ENV,
    00551   PCL_PAPERSIZE_C5_ENV,
    00552   PCL_PAPERSIZE_C6_ENV,
    00553   -1,
    00554 };
    00555
    00556 static const short ljbig_papersizes[] =
    00557 {
    00558   PCL_PAPERSIZE_EXECUTIVE,
    00559   PCL_PAPERSIZE_STATEMENT,
    00560   PCL_PAPERSIZE_LETTER,
    00561   PCL_PAPERSIZE_LEGAL,
    00562   PCL_PAPERSIZE_TABLOID,
    00563   PCL_PAPERSIZE_A5,
    00564   PCL_PAPERSIZE_A4,
    00565   PCL_PAPERSIZE_A3,
    00566   PCL_PAPERSIZE_JIS_B5,
    00567   PCL_PAPERSIZE_JIS_B4,                /* Guess */
    00568   PCL_PAPERSIZE_4x6,
    00569   PCL_PAPERSIZE_5x8,
    00570   PCL_PAPERSIZE_MONARCH_ENV,
    00571   PCL_PAPERSIZE_COMMERCIAL10_ENV,
    00572   PCL_PAPERSIZE_DL_ENV,
    00573   PCL_PAPERSIZE_C5_ENV,
    00574   PCL_PAPERSIZE_C6_ENV,
    00575   -1,
    00576 };
    00577
    00578 static const short basic_papertypes[] =
    00579 {
    00580   PCL_PAPERTYPE_PLAIN,
    00581   PCL_PAPERTYPE_BOND,
    00582   PCL_PAPERTYPE_PREMIUM,
    00583   PCL_PAPERTYPE_GLOSSY,
    00584   PCL_PAPERTYPE_TRANS,
    00585   -1,
    00586 };
    00587
    00588 static const short new_papertypes[] =
    00589 {
    00590   PCL_PAPERTYPE_PLAIN,
    00591   PCL_PAPERTYPE_BOND,
    00592   PCL_PAPERTYPE_PREMIUM,
    00593   PCL_PAPERTYPE_GLOSSY,
    00594   PCL_PAPERTYPE_TRANS,
    00595   PCL_PAPERTYPE_QPHOTO,
    00596   PCL_PAPERTYPE_QTRANS,
    00597   -1,
    00598 };
    00599
    00600 static const short laserjet_papersources[] =
    00601 {
    00602   PCL_PAPERSOURCE_STANDARD,
    00603   PCL_PAPERSOURCE_MANUAL,
    00604   PCL_PAPERSOURCE_LJ_TRAY1,
    00605   PCL_PAPERSOURCE_LJ_TRAY2,
    00606   PCL_PAPERSOURCE_LJ_TRAY3,
    00607   PCL_PAPERSOURCE_LJ_TRAY4,
    00608   -1,
    00609 };
    00610
    00611 static const short dj340_papersources[] =
    00612 {
    00613   PCL_PAPERSOURCE_STANDARD,
    00614   PCL_PAPERSOURCE_MANUAL,
    00615   PCL_PAPERSOURCE_340_PCSF,
    00616   PCL_PAPERSOURCE_340_DCSF,
    00617   -1,
    00618 };
    00619
    00620 static const short dj_papersources[] =
    00621 {
    00622   PCL_PAPERSOURCE_STANDARD,
    00623   PCL_PAPERSOURCE_MANUAL,
    00624   PCL_PAPERSOURCE_DJ_TRAY,
    00625   -1,
    00626 };
    00627
    00628 static const short dj2500_papersources[] =
    00629 {
    00630   PCL_PAPERSOURCE_STANDARD,
    00631   PCL_PAPERSOURCE_MANUAL,
    00632   PCL_PAPERSOURCE_DJ_AUTO,
    00633   PCL_PAPERSOURCE_DJ_TRAY,
    00634   PCL_PAPERSOURCE_DJ_TRAY2,
    00635   PCL_PAPERSOURCE_DJ_OPTIONAL,
    00636   -1,
    00637 };
    00638
    00639 static const short standard_papersources[] =
    00640 {
    00641   PCL_PAPERSOURCE_STANDARD,
    00642   -1
    00643 };
    00644
    00645 static const pcl_cap_t pcl_model_capabilities[] =
    00646 {
    00647   /* Default/unknown printer - assume laserjet */
    00648   { 0,
    00649     17 * 72 / 2, 14 * 72,               /* Max paper size */
    00650     1, 1,                               /* Min paper size */
    00651     PCL_RES_150_150 | PCL_RES_300_300,  /* Resolutions */
    00652     {12, 12, 18, 18},                   /* non-A4 Margins */
    00653     {12, 12, 10, 10},                   /* A4 Margins */
    00654     PCL_COLOR_NONE,
    00655     PCL_PRINTER_LJ,
    00656     standard_papersizes,
    00657     emptylist,
    00658     emptylist,
    00659   },
    00660   /* DesignJet 230/430 (monochrome ) */
    00661   { 10230,
    00662     36 * 72, 150 * 12 * 72,             /* 150ft in roll mode, 64" in sheet */
    00663     830 * 72 / 100, 583 * 72 / 100,     /* 8.3" wide min in sheet mode */
    00664     PCL_RES_300_300 | PCL_RES_600_600,
    00665     {49, 49, 15, 15},
    00666     {49, 49, 15, 15},
    00667     PCL_COLOR_NONE,
    00668     PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE | PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_NEW_ERG,
    00669     letter_only_papersizes,
    00670     basic_papertypes,
    00671     standard_papersources,
    00672   },
    00673   /* DesignJet 250C/450C/455CA/488CA */
    00674   /* The "CA" versions have a "software RIP" but are the same hardware */
    00675   { 10250,
    00676     36 * 72, 150 * 12 * 72,             /* 150ft in roll mode, 64" in sheet */
    00677     830 * 72 / 100, 583 * 72 / 100,     /* 8.3" wide min in sheet mode */
    00678     PCL_RES_300_300 | PCL_RES_600_600_MONO,
    00679     {49, 49, 15, 15},
    00680     {49, 49, 15, 15},
    00681     PCL_COLOR_CMYK,
    00682     PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE | PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_NEW_ERG,
    00683     letter_only_papersizes,
    00684     basic_papertypes,
    00685     standard_papersources,
    00686   },
    00687   /* DesignJet 700 (monochrome) */
    00688   { 10700,
    00689     36 * 72, 150 * 12 * 72,             /* 150ft in roll mode, 64" in sheet */
    00690     830 * 72 / 100, 583 * 72 / 100,     /* 8.3" wide min in sheet mode */
    00691     PCL_RES_300_300 | PCL_RES_600_600,
    00692     {30, 30, 15, 15},           /* These margins are for sheet mode FIX */
    00693     {30, 30, 15, 15},
    00694     PCL_COLOR_NONE,
    00695     PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE | PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_NEW_ERG,
    00696     letter_only_papersizes,
    00697     basic_papertypes,
    00698     standard_papersources,
    00699   },
    00700   /* DesignJet 750C */
    00701   { 10750,
    00702     36 * 72, 150 * 12 * 72,             /* 150ft in roll mode, 64" in sheet */
    00703     830 * 72 / 100, 583 * 72 / 100,     /* 8.3" wide min in sheet mode */
    00704     PCL_RES_300_300 | PCL_RES_600_600_MONO,
    00705     {30, 30, 15, 15},   /* These margins are for roll mode FIX */
    00706     {30, 30, 15, 15},
    00707     PCL_COLOR_CMYK,
    00708     PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE | PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_NEW_ERG,
    00709     letter_only_papersizes,
    00710     basic_papertypes,
    00711     standard_papersources,
    00712   },
    00713   /* DesignJet 2000C/2500C (36" wide) */
    00714   { 12500,      /* Deskjet 2500 already has "2500" */
    00715     36 * 72, 150 * 12 * 72,             /* 150ft in roll mode, 64" in sheet */
    00716     830 * 72 / 100, 583 * 72 / 100,     /* 8.3" wide min in sheet mode */
    00717     PCL_RES_300_300 | PCL_RES_600_600_MONO,
    00718     {49, 49, 15, 15},           /* Check/Fix */
    00719     {49, 49, 15, 15},
    00720     PCL_COLOR_CMYK,
    00721     PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE | PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_NEW_ERG,
    00722     letter_only_papersizes,
    00723     basic_papertypes,
    00724     standard_papersources,
    00725   },
    00726   /* DesignJet 3000C/3500C (54" wide) */
    00727   { 13500,      /* Deskjet 2500 already has "2500" */
    00728     54 * 72, 150 * 12 * 72,             /* 150ft in roll mode, 64" in sheet */
    00729     830 * 72 / 100, 583 * 72 / 100,     /* 8.3" wide min in sheet mode */
    00730     PCL_RES_300_300 | PCL_RES_600_600_MONO,
    00731     {49, 49, 15, 15},           /* Check/Fix */
    00732     {49, 49, 15, 15},
    00733     PCL_COLOR_CMYK,
    00734     PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE | PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_NEW_ERG,
    00735     letter_only_papersizes,
    00736     basic_papertypes,
    00737     standard_papersources,
    00738   },
    00739   /* Deskjet 340 */
    00740   { 340,
    00741     17 * 72 / 2, 14 * 72,
    00742     1, 1,                               /* Min paper size */
    00743     PCL_RES_150_150 | PCL_RES_300_300,
    00744     {6, 48, 18, 18},    /* from bpd07933.pdf */
    00745     {6, 48, 10, 11},    /* from bpd07933.pdf */
    00746     PCL_COLOR_CMY,
    00747     PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
    00748     dj340_papersizes,
    00749     basic_papertypes,
    00750     dj340_papersources,
    00751   },
    00752   /* Deskjet 400 */
    00753   { 400,
    00754     17 * 72 / 2, 14 * 72,
    00755     1, 1,                               /* Min paper size */
    00756     PCL_RES_150_150 | PCL_RES_300_300,
    00757     {7, 41, 18, 18},
    00758     {7, 41, 10, 10},    /* Check/Fix */
    00759     PCL_COLOR_CMY,
    00760     PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
    00761     dj400_papersizes,
    00762     basic_papertypes,
    00763     emptylist,
    00764   },
    00765   /* Deskjet 500, 520. Lexmark 4076 */
    00766   { 500,
    00767     17 * 72 / 2, 14 * 72,
    00768     1, 1,                               /* Min paper size */
    00769     PCL_RES_150_150 | PCL_RES_300_300,
    00770     {7, 41, 18, 18},
    00771     {7, 41, 10, 10},    /* Check/Fix */
    00772     PCL_COLOR_NONE,
    00773     PCL_PRINTER_DJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
    00774     dj500_papersizes,
    00775     basic_papertypes,
    00776     dj_papersources,
    00777   },
    00778   /* Deskjet 500C */
    00779   { 501,
    00780     17 * 72 / 2, 14 * 72,
    00781     1, 1,                               /* Min paper size */
    00782     PCL_RES_150_150 | PCL_RES_300_300,
    00783     {7, 33, 18, 18},
    00784     {7, 33, 10, 10},    /* Check/Fix */
    00785     PCL_COLOR_CMY,
    00786     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
    00787     dj500_papersizes,
    00788     basic_papertypes,
    00789     dj_papersources,
    00790   },
    00791   /* Deskjet 540C */
    00792   { 540,
    00793     17 * 72 / 2, 14 * 72,
    00794     1, 1,                               /* Min paper size */
    00795     PCL_RES_150_150 | PCL_RES_300_300,
    00796     {7, 33, 18, 18},
    00797     {7, 33, 10, 10},    /* Check/Fix */
    00798     PCL_COLOR_CMY,
    00799     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
    00800       PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
    00801     dj540_papersizes,
    00802     basic_papertypes,
    00803     dj_papersources,
    00804   },
    00805   /* Deskjet 550C, 560C */
    00806   { 550,
    00807     17 * 72 / 2, 14 * 72,
    00808     1, 1,                               /* Min paper size */
    00809     PCL_RES_150_150 | PCL_RES_300_300,
    00810     {3, 33, 18, 18},
    00811     {5, 33, 10, 10},
    00812     PCL_COLOR_CMYK,
    00813     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
    00814 /* The 550/560 support COM10 and DL envelope, but the control codes
    00815    are negative, indicating landscape mode. This needs thinking about! */
    00816     dj340_papersizes,
    00817     basic_papertypes,
    00818     dj_papersources,
    00819   },
    00820   /* Deskjet 600/600C */
    00821   { 600,
    00822     17 * 72 / 2, 14 * 72,
    00823     5 * 72, 583 * 72 / 100,             /* Min paper size */
    00824     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_300 | PCL_RES_600_600_MONO,
    00825     {0, 33, 18, 18},
    00826     {0, 33, 10, 10},    /* Check/Fix */
    00827     PCL_COLOR_CMY,
    00828     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
    00829       PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
    00830     dj600_papersizes,
    00831     basic_papertypes,
    00832     emptylist,
    00833   },
    00834   /* Deskjet 6xx series */
    00835   { 601,
    00836     17 * 72 / 2, 14 * 72,
    00837     1, 1,                               /* Min paper size */
    00838     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_300 | PCL_RES_600_600_MONO,
    00839     {0, 33, 18, 18},
    00840     {0, 33, 10, 10},    /* Check/Fix */
    00841     PCL_COLOR_CMYK,
    00842     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
    00843       PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
    00844     dj600_papersizes,
    00845     basic_papertypes,
    00846     emptylist,
    00847   },
    00848   /* Deskjet 69x series (Photo Capable) */
    00849   { 690,
    00850     17 * 72 / 2, 14 * 72,
    00851     1, 1,                               /* Min paper size */
    00852     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_300 | PCL_RES_600_600,
    00853     {0, 33, 18, 18},
    00854     {0, 33, 10, 10},    /* Check/Fix */
    00855     PCL_COLOR_CMYK | PCL_COLOR_CMYKcm,
    00856     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
    00857       PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
    00858     dj600_papersizes,
    00859     basic_papertypes,
    00860     emptylist,
    00861   },
    00862   /* Deskjet 850/855/870/890 (C-RET) */
    00863   { 800,
    00864     17 * 72 / 2, 14 * 72,
    00865     1, 1,                               /* Min paper size */
    00866     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600_MONO,
    00867     {3, 33, 18, 18},
    00868     {5, 33, 10, 10},
    00869     PCL_COLOR_CMYK | PCL_COLOR_CMYK4,
    00870     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
    00871       PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
    00872     dj600_papersizes,
    00873     basic_papertypes,
    00874     emptylist,
    00875   },
    00876   /* Deskjet 810C, 812C, 840C, 842C, 845C, 895C (C-RET) */
    00877   { 840,
    00878     17 * 72 / 2, 14 * 72,
    00879     1, 1,                               /* Min paper size */
    00880     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_300 | PCL_RES_600_600,
    00881     {0, 33, 18, 18},
    00882     {0, 33, 10, 10},    /* Check/Fix */
    00883     PCL_COLOR_CMYK | PCL_COLOR_CMYK4b,
    00884     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
    00885       PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
    00886     dj600_papersizes,
    00887     basic_papertypes,
    00888     emptylist,
    00889   },
    00890   /* Deskjet 900 series, 1220C, PhotoSmart P1000/P1100 */
    00891   { 900,
    00892     17 * 72 / 2, 14 * 72,
    00893     1, 1,                               /* Min paper size */
    00894     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600 /* | PCL_RES_1200_600 | PCL_RES_2400_600 */,
    00895     {3, 33, 18, 18},
    00896     {5, 33, 10, 10},    /* Oliver Vecernik */
    00897     PCL_COLOR_CMYK,
    00898     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
    00899       PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE | PCL_PRINTER_DUPLEX,
    00900     dj600_papersizes,
    00901     basic_papertypes,
    00902     emptylist,
    00903   },
    00904   /* Deskjet 1220C (or other large format 900) */
    00905   { 901,
    00906     13 * 72, 19 * 72,
    00907     1, 1,                               /* Min paper size */
    00908     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600 /* | PCL_RES_1200_600 | PCL_RES_2400_600 */,
    00909     {3, 33, 18, 18},
    00910     {5, 33, 10, 10},
    00911     PCL_COLOR_CMYK,
    00912     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
    00913       PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
    00914     dj1220_papersizes,
    00915     basic_papertypes,
    00916     emptylist,
    00917   },
    00918   /* Deskjet 1100C, 1120C */
    00919   { 1100,
    00920     13 * 72, 19 * 72,
    00921     1, 1,                               /* Min paper size */
    00922     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600_MONO,
    00923     {3, 33, 18, 18},
    00924     {5, 33, 10, 10},
    00925     PCL_COLOR_CMYK | PCL_COLOR_CMYK4,
    00926     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
    00927       PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
    00928     dj1100_papersizes,
    00929     basic_papertypes,
    00930     dj_papersources,
    00931   },
    00932   /* Deskjet 1200C */
    00933   { 1200,
    00934     17 * 72 / 2, 14 * 72,
    00935     1, 1,                               /* Min paper size */
    00936     PCL_RES_150_150 | PCL_RES_300_300,
    00937     {12, 12, 18, 18},
    00938     {12, 12, 10, 10},   /* Check/Fix */
    00939     PCL_COLOR_CMY,
    00940     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
    00941       PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
    00942     dj1200_papersizes,
    00943     basic_papertypes,
    00944     dj_papersources,
    00945   },
    00946   /* Deskjet 1600C */
    00947   { 1600,
    00948     17 * 72 / 2, 14 * 72,
    00949     1, 1,                               /* Min paper size */
    00950     PCL_RES_150_150 | PCL_RES_300_300,
    00951     {12, 12, 18, 18},
    00952     {12, 12, 10, 10},   /* Check/Fix */
    00953     PCL_COLOR_CMYK,
    00954     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
    00955       PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
    00956     dj1200_papersizes,
    00957     basic_papertypes,
    00958     dj_papersources,
    00959   },
    00960   /* Deskjet 2000 */
    00961   { 2000,
    00962     17 * 72 / 2, 14 * 72,
    00963     1, 1,                               /* Min paper size */
    00964     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
    00965     {0, 35, 18, 18},                    /* Michel Goraczko */
    00966     {0, 35, 10, 10},    /* Check/Fix */
    00967     PCL_COLOR_CMYK,
    00968     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
    00969       PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
    00970     dj2000_papersizes,
    00971     new_papertypes,
    00972     dj_papersources,
    00973   },
    00974   /* Deskjet 2500 */
    00975   { 2500,
    00976     13 * 72, 19 * 72,
    00977     1, 1,                               /* Min paper size */
    00978     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
    00979     {12, 12, 18, 18},
    00980     {12, 12, 10, 10},   /* Check/Fix */
    00981     PCL_COLOR_CMYK,
    00982     PCL_PRINTER_DJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_MEDIATYPE |
    00983       PCL_PRINTER_CUSTOM_SIZE | PCL_PRINTER_BLANKLINE,
    00984     dj2500_papersizes,
    00985     new_papertypes,
    00986     dj2500_papersources,
    00987   },
    00988   /* LaserJet II series */
    00989   { 2,
    00990     17 * 72 / 2, 14 * 72,
    00991     1, 1,                               /* Min paper size */
    00992     PCL_RES_150_150 | PCL_RES_300_300,
    00993     {12, 12, 18, 18},
    00994     {12, 12, 10, 10},   /* Check/Fix */
    00995     PCL_COLOR_NONE,
    00996     PCL_PRINTER_LJ,
    00997     ljsmall_papersizes,
    00998     emptylist,
    00999     laserjet_papersources,
    01000   },
    01001   /* LaserJet IIP (TIFF but no blankline) */
    01002   { 21,
    01003     17 * 72 / 2, 14 * 72,
    01004     1, 1,                               /* Min paper size */
    01005     PCL_RES_150_150 | PCL_RES_300_300,
    01006     {12, 12, 18, 18},
    01007     {12, 12, 10, 10},   /* Check/Fix */
    01008     PCL_COLOR_NONE,
    01009     PCL_PRINTER_LJ | PCL_PRINTER_TIFF,
    01010     ljsmall_papersizes,
    01011     emptylist,
    01012     laserjet_papersources,
    01013   },
    01014   /* LaserJet III series */
    01015   { 3,
    01016     17 * 72 / 2, 14 * 72,
    01017     1, 1,                               /* Min paper size */
    01018     PCL_RES_150_150 | PCL_RES_300_300,
    01019     {12, 12, 18, 18},
    01020     {12, 12, 10, 10},   /* Check/Fix */
    01021     PCL_COLOR_NONE,
    01022     PCL_PRINTER_LJ | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
    01023     ljsmall_papersizes,
    01024     emptylist,
    01025     laserjet_papersources,
    01026   },
    01027   /* LaserJet 4L */
    01028   { 4,
    01029     17 * 72 / 2, 14 * 72,
    01030     1, 1,                               /* Min paper size */
    01031     PCL_RES_150_150 | PCL_RES_300_300,
    01032     {12, 12, 18, 18},
    01033     {12, 12, 10, 10},   /* Check/Fix */
    01034     PCL_COLOR_NONE,
    01035     PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
    01036     ljsmall_papersizes,
    01037     emptylist,
    01038     laserjet_papersources,
    01039   },
    01040   /* LaserJet 4V */
    01041   { 5,
    01042     13 * 72, 19 * 72,
    01043     1, 1,                               /* Min paper size */
    01044     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
    01045     {12, 12, 18, 18},
    01046     {12, 12, 10, 10},   /* Check/Fix */
    01047     PCL_COLOR_NONE,
    01048     PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE,
    01049     ljbig_papersizes,
    01050     emptylist,
    01051     laserjet_papersources,
    01052   },
    01053   /* LaserJet 4Si */
    01054   { 51,
    01055     13 * 72, 19 * 72,
    01056     1, 1,                               /* Min paper size */
    01057     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
    01058     {12, 12, 18, 18},
    01059     {12, 12, 10, 10},   /* Check/Fix */
    01060     PCL_COLOR_NONE,
    01061     PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE |
    01062       PCL_PRINTER_DUPLEX,
    01063     ljbig_papersizes,
    01064     emptylist,
    01065     laserjet_papersources,
    01066   },
    01067   /* LaserJet 4 series (except as above), 5 series, 6 series */
    01068   { 6,
    01069     17 * 72 / 2, 14 * 72,
    01070     1, 1,                               /* Min paper size */
    01071     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
    01072     {12, 12, 18, 18},
    01073     {12, 12, 10, 10},   /* Check/Fix */
    01074     PCL_COLOR_NONE,
    01075     PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE |
    01076       PCL_PRINTER_DUPLEX,
    01077     ljsmall_papersizes,
    01078     emptylist,
    01079     laserjet_papersources,
    01080   },
    01081   /* LaserJet 5Si */
    01082   { 7,
    01083     13 * 72, 19 * 72,
    01084     1, 1,                               /* Min paper size */
    01085     PCL_RES_150_150 | PCL_RES_300_300 | PCL_RES_600_600,
    01086     {12, 12, 18, 18},
    01087     {12, 12, 10, 10},   /* Check/Fix */
    01088     PCL_COLOR_NONE,
    01089     PCL_PRINTER_LJ | PCL_PRINTER_NEW_ERG | PCL_PRINTER_TIFF | PCL_PRINTER_BLANKLINE |
    01090       PCL_PRINTER_DUPLEX,
    01091     ljbig_papersizes,
    01092     emptylist,
    01093     laserjet_papersources,
    01094   },
    01095 };
    01096
    01097
    01098 static const char standard_sat_adjustment[] =
    01099 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    01100 "<gimp-print>\n"
    01101 "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n"
    01102 "<sequence count=\"48\" lower-bound=\"0\" upper-bound=\"4\">\n"
    01103 /* C */  "1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 "  /* B */
    01104 /* B */  "1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 "  /* M */
    01105 /* M */  "1.00 0.95 0.90 0.90 0.90 0.90 0.90 0.90 "  /* R */
    01106 /* R */  "0.90 0.95 0.95 1.00 1.00 1.00 1.00 1.00 "  /* Y */
    01107 /* Y */  "1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 "  /* G */
    01108 /* G */  "1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 "  /* C */
    01109 "</sequence>\n"
    01110 "</curve>\n"
    01111 "</gimp-print>\n";
    01112
    01113 static const char standard_lum_adjustment[] =
    01114 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    01115 "<gimp-print>\n"
    01116 "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n"
    01117 "<sequence count=\"48\" lower-bound=\"0\" upper-bound=\"4\">\n"
    01118 /* C */  "0.50 0.52 0.56 0.60 0.66 0.71 0.74 0.77 "  /* B */
    01119 /* B */  "0.81 0.79 0.74 0.68 0.70 0.74 0.77 0.82 "  /* M */
    01120 /* M */  "0.88 0.93 0.95 0.97 0.97 0.96 0.95 0.95 "  /* R */
    01121 /* R */  "0.95 0.96 0.97 0.98 0.99 1.00 1.00 1.00 "  /* Y */
    01122 /* Y */  "1.00 0.97 0.94 0.92 0.90 0.88 0.85 0.79 "  /* G */
    01123 /* G */  "0.69 0.64 0.58 0.54 0.54 0.54 0.53 0.51 "  /* C */
    01124 "</sequence>\n"
    01125 "</curve>\n"
    01126 "</gimp-print>\n";
    01127
    01128 static const char standard_hue_adjustment[] =
    01129 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    01130 "<gimp-print>\n"
    01131 "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\">\n"
    01132 "<sequence count=\"48\" lower-bound=\"-6\" upper-bound=\"6\">\n"
    01133 /* C */  "0.00 0.06 0.10 0.10 0.06 -.01 -.09 -.17 "  /* B */
    01134 /* B */  "-.25 -.33 -.38 -.38 -.36 -.34 -.34 -.34 "  /* M */
    01135 /* M */  "-.34 -.34 -.36 -.40 -.50 -.40 -.30 -.20 "  /* R */
    01136 /* R */  "-.12 -.07 -.04 -.02 0.00 0.00 0.00 0.00 "  /* Y */
    01137 /* Y */  "0.00 0.00 0.00 -.05 -.10 -.15 -.22 -.24 "  /* G */
    01138 /* G */  "-.26 -.30 -.33 -.28 -.25 -.20 -.13 -.06 "  /* C */
    01139 "</sequence>\n"
    01140 "</curve>\n"
    01141 "</gimp-print>\n";
    01142
    01143 static const stp_parameter_t the_parameters[] =
    01144 {
    01145   {
    01146     "PageSize", N_("Page Size"), N_("Basic Printer Setup"),
    01147     N_("Size of the paper being printed to"),
    01148     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
    01149     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
    01150   },
    01151   {
    01152     "MediaType", N_("Media Type"), N_("Basic Printer Setup"),
    01153     N_("Type of media (plain paper, photo paper, etc.)"),
    01154     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
    01155     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
    01156   },
    01157   {
    01158     "InputSlot", N_("Media Source"), N_("Basic Printer Setup"),
    01159     N_("Source (input slot) of the media"),
    01160     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
    01161     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
    01162   },
    01163   {
    01164     "Resolution", N_("Resolution"), N_("Basic Printer Setup"),
    01165     N_("Resolution and quality of the print"),
    01166     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
    01167     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
    01168   },
    01169   {
    01170     "InkType", N_("Ink Type"), N_("Advanced Printer Setup"),
    01171     N_("Type of ink in the printer"),
    01172     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
    01173     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
    01174   },
    01175   {
    01176     "InkChannels", N_("Ink Channels"), N_("Advanced Printer Functionality"),
    01177     N_("Ink Channels"),
    01178     STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
    01179     STP_PARAMETER_LEVEL_INTERNAL, 0, 0, -1, 0, 0
    01180   },
    01181   {
    01182     "PrintingMode", N_("Printing Mode"), N_("Core Parameter"),
    01183     N_("Printing Output Mode"),
    01184     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
    01185     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
    01186   },
    01187   {
    01188     "Duplex", N_("Double-Sided Printing"), N_("Basic Printer Setup"),
    01189     N_("Duplex/Tumble Setting"),
    01190     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
    01191     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
    01192   },
    01193 };
    01194
    01195 static const int the_parameter_count =
    01196 sizeof(the_parameters) / sizeof(const stp_parameter_t);
    01197
    01198 typedef struct
    01199 {
    01200   const stp_parameter_t param;
    01201   double min;
    01202   double max;
    01203   double defval;
    01204   int color_only;
    01205 } float_param_t;
    01206
    01207 static const float_param_t float_parameters[] =
    01208 {
    01209   {
    01210     {
    01211       "CyanDensity", N_("Cyan Balance"), N_("Output Level Adjustment"),
    01212       N_("Adjust the cyan balance"),
    01213       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
    01214       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 1, 1, 0
    01215     }, 0.0, 2.0, 1.0, 1
    01216   },
    01217   {
    01218     {
    01219       "MagentaDensity", N_("Magenta Balance"), N_("Output Level Adjustment"),
    01220       N_("Adjust the magenta balance"),
    01221       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
    01222       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 2, 1, 0
    01223     }, 0.0, 2.0, 1.0, 1
    01224   },
    01225   {
    01226     {
    01227       "YellowDensity", N_("Yellow Balance"), N_("Output Level Adjustment"),
    01228       N_("Adjust the yellow balance"),
    01229       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
    01230       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 3, 1, 0
    01231     }, 0.0, 2.0, 1.0, 1
    01232   },
    01233   {
    01234     {
    01235       "BlackDensity", N_("Black Balance"), N_("Output Level Adjustment"),
    01236       N_("Adjust the black balance"),
    01237       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
    01238       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 0, 1, 0
    01239     }, 0.0, 2.0, 1.0, 1
    01240   },
    01241   {
    01242     {
    01243       "LightCyanTransition", N_("Light Cyan Transition"), N_("Advanced Ink Adjustment"),
    01244       N_("Light Cyan Transition"),
    01245       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
    01246       STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, -1, 1, 0
    01247     }, 0.0, 5.0, 1.0, 1
    01248   },
    01249   {
    01250     {
    01251       "LightMagentaTransition", N_("Light Magenta Transition"), N_("Advanced Ink Adjustment"),
    01252       N_("Light Magenta Transition"),
    01253       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
    01254       STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, -1, 1, 0
    01255     }, 0.0, 5.0, 1.0, 1
    01256   },
    01257 };
    01258
    01259 static const int float_parameter_count =
    01260 sizeof(float_parameters) / sizeof(const float_param_t);
    01261
    01262 /*
    01263  * Convert a name into it's option value
    01264  */
    01265
    01266 static int pcl_string_to_val(const char *string,                /* I: String */
    01267                            const pcl_t *options,        /* I: Options */
    01268                            int num_options)             /* I: Num options */
    01269 {
    01270
    01271   int i;
    01272   int code = -1;
    01273
    01274  /*
    01275   * Look up the string in the table and convert to the code.
    01276   */
    01277
    01278   for (i=0; i<num_options; i++) {
    01279     if (!strcmp(string, options[i].pcl_name)) {
    01280        code=options[i].pcl_code;
    01281        break;
    01282        }
    01283   }
    01284
    01285   stp_deprintf(STP_DBG_PCL, "String: %s, Code: %d\n", string, code);
    01286
    01287   return(code);
    01288 }
    01289
    01290 /*
    01291  * Convert a value into it's option name
    01292  */
    01293
    01294 static const char * pcl_val_to_string(int code,                 /* I: Code */
    01295                            const pcl_t *options,        /* I: Options */
    01296                            int num_options)             /* I: Num options */
    01297 {
    01298
    01299   int i;
    01300   const char *string = NULL;
    01301
    01302  /*
    01303   * Look up the code in the table and convert to the string.
    01304   */
    01305
    01306   for (i=0; i<num_options; i++) {
    01307     if (code == options[i].pcl_code) {
    01308        string=options[i].pcl_name;
    01309        break;
    01310        }
    01311   }
    01312
    01313   stp_deprintf(STP_DBG_PCL, "Code: %d, String: %s\n", code, string);
    01314
    01315   return(string);
    01316 }
    01317
    01318 static const char * pcl_val_to_text(int code,                   /* I: Code */
    01319                            const pcl_t *options,        /* I: Options */
    01320                            int num_options)             /* I: Num options */
    01321 {
    01322
    01323   int i;
    01324   const char *string = NULL;
    01325
    01326  /*
    01327   * Look up the code in the table and convert to the string.
    01328   */
    01329
    01330   for (i=0; i<num_options; i++) {
    01331     if (code == options[i].pcl_code) {
    01332        string=options[i].pcl_text;
    01333        break;
    01334        }
    01335   }
    01336
    01337   stp_deprintf(STP_DBG_PCL, "Code: %d, String: %s\n", code, string);
    01338
    01339   return(string);
    01340 }
    01341
    01342 static const double dot_sizes[] = { 0.5, 0.832, 1.0 };
    01343 static const double dot_sizes_cret[] = { 1.0, 1.0, 1.0 };
    01344
    01345 static const stp_dotsize_t variable_dotsizes[] =
    01346 {
    01347   { 0x1, 0.5 },
    01348   { 0x2, 0.67 },
    01349   { 0x3, 1.0 }
    01350 };
    01351
    01352 static const stp_shade_t variable_shades[] =
    01353 {
    01354   { 0.38, 3, variable_dotsizes },
    01355   { 1.0, 3, variable_dotsizes }
    01356 };
    01357
    01358 /*
    01359  * pcl_get_model_capabilities() - Return struct of model capabilities
    01360  */
    01361
    01362 static const pcl_cap_t *                                /* O: Capabilities */
    01363 pcl_get_model_capabilities(int model)   /* I: Model */
    01364 {
    01365   int i;
    01366   int models= sizeof(pcl_model_capabilities) / sizeof(pcl_cap_t);
    01367   for (i=0; i<models; i++) {
    01368     if (pcl_model_capabilities[i].model == model) {
    01369       return &(pcl_model_capabilities[i]);
    01370     }
    01371   }
    01372   stp_erprintf("pcl: model %d not found in capabilities list.\n",model);
    01373   return &(pcl_model_capabilities[0]);
    01374 }
    01375
    01376 /*
    01377  * Convert Media size name into PCL media code for printer
    01378  */
    01379
    01380 static int pcl_convert_media_size(const char *media_size,       /* I: Media size string */
    01381                                   int  model)           /* I: model number */
    01382 {
    01383
    01384   int i;
    01385   int media_code = 0;
    01386   const pcl_cap_t *caps;
    01387
    01388  /*
    01389   * First look up the media size in the table and convert to the code.
    01390   */
    01391
    01392   media_code = pcl_string_to_val(media_size, pcl_media_sizes,
    01393                                  NUM_PRINTER_PAPER_SIZES);
    01394
    01395   stp_deprintf(STP_DBG_PCL, "Media Size: %s, Code: %d\n", media_size, media_code);
    01396
    01397  /*
    01398   * Now see if the printer supports the code found.
    01399   */
    01400
    01401   if (media_code != -1) {
    01402     caps = pcl_get_model_capabilities(model);
    01403
    01404     for (i=0; (i<NUM_PRINTER_PAPER_SIZES) && (caps->paper_sizes[i] != -1); i++) {
    01405       if (media_code == (int) caps->paper_sizes[i])
    01406         return(media_code);             /* Is supported */
    01407     }
    01408
    01409     stp_deprintf(STP_DBG_PCL, "Media Code %d not supported by printer model %d.\n",
    01410       media_code, model);
    01411     return(-1);                         /* Not supported */
    01412   }
    01413   else
    01414     return(-1);                         /* Not supported */
    01415 }
    01416
    01417
    01418 static const stp_param_string_t ink_types[] =
    01419 {
    01420   { "CMYK",     N_ ("Color + Black Cartridges") },
    01421   { "Photo",    N_ ("Color + Photo Cartridges") }
    01422 };
    01423
    01424 /*
    01425  * Duplex support - modes available
    01426  * Note that the internal names MUST match those in cups/genppd.c else the
    01427  * PPD files will not be generated correctly
    01428  */
    01429
    01430 static const stp_param_string_t duplex_types[] =
    01431 {
    01432   { "None",             N_ ("Off") },
    01433   { "DuplexNoTumble",   N_ ("Long Edge (Standard)") },
    01434   { "DuplexTumble",     N_ ("Short Edge (Flip)") }
    01435 };
    01436 #define NUM_DUPLEX (sizeof (duplex_types) / sizeof (stp_param_string_t))
    01437
    01438 /*
    01439  * 'pcl_papersize_valid()' - Is the paper size valid for this printer.
    01440  */
    01441
    01442 static const int
    01443 pcl_papersize_valid(const stp_papersize_t *pt,
    01444                     int model)
    01445 {
    01446
    01447   const pcl_cap_t *caps = pcl_get_model_capabilities(model);
    01448
    01449 #ifdef PCL_NO_CUSTOM_PAPERSIZES
    01450   int use_custom = 0;
    01451 #else
    01452   int use_custom = ((caps->stp_printer_type & PCL_PRINTER_CUSTOM_SIZE)
    01453                      == PCL_PRINTER_CUSTOM_SIZE);
    01454 #endif
    01455
    01456   unsigned int pwidth = pt->width;
    01457   unsigned int pheight = pt->height;
    01458
    01459 /*
    01460  * This function decides whether a paper size is allowed for the
    01461  * current printer. The DeskJet feed mechanisms set a minimum and
    01462  * maximum size for the paper, BUT some of the directly supported
    01463  * media sizes are less than this minimum (eg card and envelopes)
    01464  * So, we allow supported sizes though, but clamp custom sizes
    01465  * to the min and max sizes.
    01466  */
    01467
    01468 /*
    01469  * Is it a valid name?
    01470  */
    01471
    01472   if (strlen(pt->name) <= 0)
    01473     return(0);
    01474
    01475 /*
    01476  * Is it a recognised supported name?
    01477  */
    01478
    01479   if (pcl_convert_media_size(pt->name, model) != -1)
    01480     return(1);
    01481
    01482 /*
    01483  * If we are not allowed to use custom paper sizes, we are done
    01484  */
    01485
    01486   if (use_custom == 0)
    01487     return(0);
    01488
    01489 /*
    01490  * We are allowed custom paper sizes. Check that the size is within
    01491  * limits.
    01492  */
    01493
    01494   if (pwidth <= caps->custom_max_width &&
    01495      pheight <= caps->custom_max_height &&
    01496      (pheight >=  caps->custom_min_height || pheight == 0) &&
    01497      (pwidth >= caps->custom_min_width || pwidth == 0))
    01498     return(1);
    01499
    01500   return(0);
    01501 }
    01502
    01503 /*
    01504  * 'pcl_parameters()' - Return the parameter values for the given parameter.
    01505  */
    01506
    01507 static stp_parameter_list_t
    01508 pcl_list_parameters(const stp_vars_t *v)
    01509 {
    01510   stp_parameter_list_t *ret = stp_parameter_list_create();
    01511   int i;
    01512   for (i = 0; i < the_parameter_count; i++)
    01513     stp_parameter_list_add_param(ret, &(the_parameters[i]));
    01514   for (i = 0; i < float_parameter_count; i++)
    01515     stp_parameter_list_add_param(ret, &(float_parameters[i].param));
    01516   return ret;
    01517 }
    01518
    01519 static void
    01520 pcl_parameters(const stp_vars_t *v, const char *name,
    01521                stp_parameter_t *description)
    01522 {
    01523   int           model = stp_get_model_id(v);
    01524   int           i;
    01525   const pcl_cap_t *caps;
    01526   description->p_type = STP_PARAMETER_TYPE_INVALID;
    01527
    01528   if (name == NULL)
    01529     return;
    01530
    01531   stp_deprintf(STP_DBG_PCL, "pcl_parameters(): Name = %s\n", name);
    01532
    01533   caps = pcl_get_model_capabilities(model);
    01534
    01535   stp_deprintf(STP_DBG_PCL, "Printer model = %d\n", model);
    01536   stp_deprintf(STP_DBG_PCL, "PageWidth = %d, PageHeight = %d\n", caps->custom_max_width, caps->custom_max_height);
    01537   stp_deprintf(STP_DBG_PCL, "MinPageWidth = %d, MinPageHeight = %d\n", caps->custom_min_width, caps->custom_min_height);
    01538   stp_deprintf(STP_DBG_PCL, "Normal Margins: top = %d, bottom = %d, left = %d, right = %d\n",
    01539     caps->normal_margins.top_margin, caps->normal_margins.bottom_margin,
    01540     caps->normal_margins.left_margin, caps->normal_margins.right_margin);
    01541   stp_deprintf(STP_DBG_PCL, "A4 Margins: top = %d, bottom = %d, left = %d, right = %d\n",
    01542     caps->a4_margins.top_margin, caps->a4_margins.bottom_margin,
    01543     caps->a4_margins.left_margin, caps->a4_margins.right_margin);
    01544   stp_deprintf(STP_DBG_PCL, "Resolutions: %d\n", caps->resolutions);
    01545   stp_deprintf(STP_DBG_PCL, "ColorType = %d, PrinterType = %d\n", caps->color_type, caps->stp_printer_type);
    01546
    01547   for (i = 0; i < float_parameter_count; i++)
    01548     if (strcmp(name, float_parameters[i].param.name) == 0)
    01549       {
    01550         stp_fill_parameter_settings(description,
    01551                                     &(float_parameters[i].param));
    01552         description->deflt.dbl = float_parameters[i].defval;
    01553         description->bounds.dbl.upper = float_parameters[i].max;
    01554         description->bounds.dbl.lower = float_parameters[i].min;
    01555       }
    01556
    01557   for (i = 0; i < the_parameter_count; i++)
    01558     if (strcmp(name, the_parameters[i].name) == 0)
    01559       {
    01560         stp_fill_parameter_settings(description, &(the_parameters[i]));
    01561         break;
    01562       }
    01563   description->deflt.str = NULL;
    01564
    01565   if (strcmp(name, "PageSize") == 0)
    01566     {
    01567       int papersizes = stp_known_papersizes();
    01568       description->bounds.str = stp_string_list_create();
    01569       for (i = 0; i < papersizes; i++)
    01570         {
    01571           const stp_papersize_t *pt = stp_get_papersize_by_index(i);
    01572           if (strlen(pt->name) > 0 && pcl_papersize_valid(pt, model))
    01573             stp_string_list_add_string(description->bounds.str,
    01574                                        pt->name, pt->text);
    01575         }
    01576       description->deflt.str =
    01577         stp_string_list_param(description->bounds.str, 0)->name;
    01578     }
    01579   else if (strcmp(name, "MediaType") == 0)
    01580   {
    01581     description->bounds.str = stp_string_list_create();
    01582     if (caps->paper_types[0] != -1)
    01583       {
    01584         for (i=0; (i < NUM_PRINTER_PAPER_TYPES) && (caps->paper_types[i] != -1); i++)
    01585           stp_string_list_add_string(description->bounds.str,
    01586                                     pcl_val_to_string(caps->paper_types[i],
    01587                                                       pcl_media_types,
    01588                                                       NUM_PRINTER_PAPER_TYPES),
    01589                                     pcl_val_to_text(caps->paper_types[i],
    01590                                                     pcl_media_types,
    01591                                                     NUM_PRINTER_PAPER_TYPES));
    01592         description->deflt.str =
    01593           stp_string_list_param(description->bounds.str, 0)->name;
    01594       }
    01595     else
    01596       description->is_active = 0;
    01597   }
    01598   else if (strcmp(name, "InputSlot") == 0)
    01599   {
    01600     description->bounds.str = stp_string_list_create();
    01601     if (caps->paper_sources[0] != -1)
    01602       {
    01603         for (i=0; (i < NUM_PRINTER_PAPER_SOURCES) && (caps->paper_sources[i] != -1); i++)
    01604           stp_string_list_add_string(description->bounds.str,
    01605                                     pcl_val_to_string(caps->paper_sources[i],
    01606                                                       pcl_media_sources,
    01607                                                       NUM_PRINTER_PAPER_SOURCES),
    01608                                     pcl_val_to_text(caps->paper_sources[i],
    01609                                                     pcl_media_sources,
    01610                                                     NUM_PRINTER_PAPER_SOURCES));
    01611         description->deflt.str =
    01612           stp_string_list_param(description->bounds.str, 0)->name;
    01613       }
    01614     else
    01615       description->is_active = 0;
    01616   }
    01617   else if (strcmp(name, "Resolution") == 0)
    01618   {
    01619     description->bounds.str = stp_string_list_create();
    01620     description->deflt.str = NULL;
    01621     for (i = 0; i < NUM_RESOLUTIONS; i++)
    01622       if (caps->resolutions & pcl_resolutions[i].pcl_code)
    01623         {
    01624           if (pcl_resolutions[i].pcl_code >= PCL_RES_300_300 &&
    01625               description->deflt.str == NULL)
    01626             description->deflt.str =
    01627               pcl_val_to_string(pcl_resolutions[i].pcl_code,
    01628                                 pcl_resolutions, NUM_RESOLUTIONS);
    01629           stp_string_list_add_string
    01630             (description->bounds.str,
    01631              pcl_val_to_string(pcl_resolutions[i].pcl_code,
    01632                                pcl_resolutions, NUM_RESOLUTIONS),
    01633              pcl_val_to_text(pcl_resolutions[i].pcl_code,
    01634                              pcl_resolutions, NUM_RESOLUTIONS));
    01635         }
    01636     if (description->deflt.str == NULL)
    01637       stp_erprintf("No default resolution set!\n");
    01638   }
    01639   else if (strcmp(name, "InkType") == 0)
    01640   {
    01641     description->bounds.str = stp_string_list_create();
    01642     if (caps->color_type & PCL_COLOR_CMYKcm)
    01643     {
    01644       description->deflt.str = ink_types[0].name;
    01645       stp_string_list_add_string(description->bounds.str,
    01646                                ink_types[0].name,_(ink_types[0].text));
    01647       stp_string_list_add_string(description->bounds.str,
    01648                                ink_types[1].name,_(ink_types[1].text));
    01649     }
    01650     else
    01651       description->is_active = 0;
    01652   }
    01653   else if (strcmp(name, "Duplex") == 0)
    01654   {
    01655     int offer_duplex=0;
    01656
    01657     description->bounds.str = stp_string_list_create();
    01658
    01659 /*
    01660  * Don't offer the Duplex/Tumble options if the JobMode parameter is
    01661  * set to "Page" Mode.
    01662  * "Page" mode is set by the Gimp Plugin, which only outputs one page at a
    01663  * time, so Duplex/Tumble is meaningless.
    01664  */
    01665
    01666     if (stp_get_string_parameter(v, "JobMode"))
    01667         offer_duplex = strcmp(stp_get_string_parameter(v, "JobMode"), "Page");
    01668     else
    01669      offer_duplex=1;
    01670
    01671     if (offer_duplex)
    01672     {
    01673       if (caps->stp_printer_type & PCL_PRINTER_DUPLEX)
    01674       {
    01675         description->deflt.str = duplex_types[0].name;
    01676         for (i=0; i < NUM_DUPLEX; i++)
    01677         {
    01678           stp_string_list_add_string(description->bounds.str,
    01679                                duplex_types[i].name,_(duplex_types[i].text));
    01680         }
    01681       }
    01682       else
    01683         description->is_active = 0;     /* Not supported by printer */
    01684     }
    01685     else
    01686       description->is_active = 0;       /* Not in "Job" mode */
    01687   }
    01688   else if (strcmp(name, "CyanDensity") == 0 ||
    01689            strcmp(name, "MagentaDensity") == 0 ||
    01690            strcmp(name, "YellowDensity") == 0 ||
    01691            strcmp(name, "BlackDensity") == 0)
    01692     {
    01693       if (caps->color_type != PCL_COLOR_NONE &&
    01694           stp_check_string_parameter(v, "PrintingMode", STP_PARAMETER_DEFAULTED) &&
    01695           strcmp(stp_get_string_parameter(v, "PrintingMode"), "Color") == 0)
    01696         description->is_active = 1;
    01697       else
    01698         description->is_active = 0;
    01699     }
    01700   else if (strcmp(name, "LightCyanTransition") == 0 ||
    01701            strcmp(name, "LightMagentaTransition") == 0)
    01702     {
    01703       if (caps->color_type & PCL_COLOR_CMYKcm &&
    01704           stp_check_string_parameter(v, "PrintingMode", STP_PARAMETER_DEFAULTED) &&
    01705           strcmp(stp_get_string_parameter(v, "PrintingMode"), "Color") == 0)
    01706         description->is_active = 1;
    01707       else
    01708         description->is_active = 0;
    01709     }
    01710   else if (strcmp(name, "InkChannels") == 0)
    01711     {
    01712       if (caps->color_type & PCL_COLOR_CMYKcm)
    01713         description->deflt.integer = 6;
    01714       else if (caps->color_type == PCL_COLOR_NONE)
    01715         description->deflt.integer = 1;
    01716       else
    01717         description->deflt.integer = 4;
    01718       description->bounds.integer.lower = -1;
    01719       description->bounds.integer.upper = -1;
    01720     }
    01721   else if (strcmp(name, "PrintingMode") == 0)
    01722     {
    01723       description->bounds.str = stp_string_list_create();
    01724       if (caps->color_type != PCL_COLOR_NONE)
    01725         stp_string_list_add_string
    01726           (description->bounds.str, "Color", _("Color"));
    01727       stp_string_list_add_string
    01728         (description->bounds.str, "BW", _("Black and White"));
    01729       description->deflt.str =
    01730         stp_string_list_param(description->bounds.str, 0)->name;
    01731     }
    01732 }
    01733
    01734
    01735 /*
    01736  * 'pcl_imageable_area()' - Return the imageable area of the page.
    01737  */
    01738 static void
    01739 internal_imageable_area(const stp_vars_t *v,     /* I */
    01740                         int  use_paper_margins,
    01741                         int  *left,     /* O - Left position in points */
    01742                         int  *right,    /* O - Right position in points */
    01743                         int  *bottom,   /* O - Bottom position in points */
    01744                         int  *top)      /* O - Top position in points */
    01745 {
    01746   int   width, height;                  /* Size of page */
    01747   const pcl_cap_t *caps;                /* Printer caps */
    01748   int   pcl_media_size;                 /* Converted media size */
    01749   const char *media_size = stp_get_string_parameter(v, "PageSize");
    01750   const stp_papersize_t *pp = NULL;
    01751   int left_margin = 0;
    01752   int right_margin = 0;
    01753   int bottom_margin = 0;
    01754   int top_margin = 0;
    01755
    01756   caps = pcl_get_model_capabilities(stp_get_model_id(v));
    01757
    01758   stp_default_media_size(v, &width, &height);
    01759
    01760 /* If we are using A4 paper, then the margins are different than any
    01761  * other paper size. This is because HP wanted to have the same printable
    01762  * width for A4 as for letter. Go figure.
    01763  */
    01764
    01765   if (!media_size)
    01766     media_size = "";
    01767   if (strlen(media_size) == 0 &&
    01768       ((pp = stp_get_papersize_by_size(stp_get_page_height(v),
    01769                                        stp_get_page_width(v))) != NULL))
    01770     media_size = pp->name;
    01771
    01772   stp_deprintf(STP_DBG_PCL, "pcl_imageable_area(): media_size: '%s'\n",
    01773                media_size);
    01774
    01775   pcl_media_size = pcl_convert_media_size(media_size, stp_get_model_id(v));
    01776   if (media_size)
    01777     pp = stp_get_papersize_by_name(media_size);
    01778   if (pp && use_paper_margins)
    01779     {
    01780       left_margin = pp->left;
    01781       right_margin = pp->right;
    01782       bottom_margin = pp->bottom;
    01783       top_margin = pp->top;
    01784     }
    01785
    01786   if (pcl_media_size == PCL_PAPERSIZE_A4)
    01787   {
    01788     left_margin = MAX(left_margin, caps->a4_margins.left_margin);
    01789     right_margin = MAX(right_margin, caps->a4_margins.right_margin);
    01790     top_margin = MAX(top_margin, caps->a4_margins.top_margin);
    01791     bottom_margin = MAX(bottom_margin, caps->a4_margins.bottom_margin);
    01792   }
    01793   else
    01794   {
    01795     left_margin = MAX(left_margin, caps->normal_margins.left_margin);
    01796     right_margin = MAX(right_margin, caps->normal_margins.right_margin);
    01797     top_margin = MAX(top_margin, caps->normal_margins.top_margin);
    01798     bottom_margin = MAX(bottom_margin, caps->normal_margins.bottom_margin);
    01799   }
    01800   *left =       left_margin;
    01801   *right =      width - right_margin;
    01802   *top =        top_margin;
    01803   *bottom =     height - bottom_margin;
    01804 }
    01805
    01806 static void
    01807 pcl_imageable_area(const stp_vars_t *v,     /* I */
    01808                    int  *left,          /* O - Left position in points */
    01809                    int  *right,         /* O - Right position in points */
    01810                    int  *bottom,        /* O - Bottom position in points */
    01811                    int  *top)           /* O - Top position in points */
    01812 {
    01813   internal_imageable_area(v, 1, left, right, bottom, top);
    01814 }
    01815
    01816 static void
    01817 pcl_limit(const stp_vars_t *v,                  /* I */
    01818           int *width,
    01819           int *height,
    01820           int *min_width,
    01821           int *min_height)
    01822 {
    01823   const pcl_cap_t *caps= pcl_get_model_capabilities(stp_get_model_id(v));
    01824   *width =      caps->custom_max_width;
    01825   *height =     caps->custom_max_height;
    01826   *min_width =  caps->custom_min_width;
    01827   *min_height = caps->custom_min_height;
    01828 }
    01829
    01830 static const char *
    01831 pcl_describe_output(const stp_vars_t *v)
    01832 {
    01833   int printing_color = 0;
    01834   int model = stp_get_model_id(v);
    01835   const pcl_cap_t *caps = pcl_get_model_capabilities(model);
    01836   const char *print_mode = stp_get_string_parameter(v, "PrintingMode");
    01837   int xdpi, ydpi;
    01838
    01839   pcl_describe_resolution(v, &xdpi, &ydpi);
    01840   if (!print_mode || strcmp(print_mode, "Color") == 0)
    01841     printing_color = 1;
    01842   if (((caps->resolutions & PCL_RES_600_600_MONO) == PCL_RES_600_600_MONO) &&
    01843       printing_color && xdpi == 600 && ydpi == 600)
    01844     printing_color = 0;
    01845   if (printing_color)
    01846     {
    01847       if ((caps->color_type & PCL_COLOR_CMY) == PCL_COLOR_CMY)
    01848         return "CMY";
    01849       else
    01850         return "CMYK";
    01851     }
    01852   else
    01853     return "Grayscale";
    01854 }
    01855
    01856 /*
    01857  * 'pcl_print()' - Print an image to an HP printer.
    01858  */
    01859
    01860 static void
    01861 pcl_printfunc(stp_vars_t *v)
    01862 {
    01863   pcl_privdata_t *pd = (pcl_privdata_t *) stp_get_component_data(v, "Driver");
    01864   int do_blank = pd->do_blank;
    01865   unsigned char *black = stp_dither_get_channel(v, STP_ECOLOR_K, 0);
    01866   unsigned char *cyan = stp_dither_get_channel(v, STP_ECOLOR_C, 0);
    01867   unsigned char *lcyan = stp_dither_get_channel(v, STP_ECOLOR_C, 1);
    01868   unsigned char *magenta = stp_dither_get_channel(v, STP_ECOLOR_M, 0);
    01869   unsigned char *lmagenta = stp_dither_get_channel(v, STP_ECOLOR_M, 1);
    01870   unsigned char *yellow = stp_dither_get_channel(v, STP_ECOLOR_Y, 0);
    01871   int len_c = stp_dither_get_last_position(v, STP_ECOLOR_C, 0);
    01872   int len_lc = stp_dither_get_last_position(v, STP_ECOLOR_C, 1);
    01873   int len_m = stp_dither_get_last_position(v, STP_ECOLOR_M, 0);
    01874   int len_lm = stp_dither_get_last_position(v, STP_ECOLOR_M, 1);
    01875   int len_y = stp_dither_get_last_position(v, STP_ECOLOR_Y, 0);
    01876   int len_k = stp_dither_get_last_position(v, STP_ECOLOR_K, 0);
    01877   int is_blank = (do_blank && (len_c == -1) && (len_lc == -1) &&
    01878                   (len_m == -1) && (len_lm == -1) && (len_y == -1) &&
    01879                   (len_k == -1));
    01880   int height = pd->height;
    01881   const char    *print_mode = stp_get_string_parameter(v, "PrintingMode");
    01882
    01883   if (is_blank && (pd->blank_lines != 0))       /* repeated blank line */
    01884     {
    01885       pd->blank_lines++;
    01886     }
    01887   else                          /* Not blank, or is first one */
    01888     {
    01889       if (! is_blank)
    01890         {
    01891           if (pd->blank_lines > 1)              /* Output accumulated lines */
    01892             {
    01893               pd->blank_lines--;                /* correct for one already output */
    01894               stp_deprintf(STP_DBG_PCL, "Blank Lines = %d\n", pd->blank_lines);
    01895               stp_zprintf(v, "\033*b%dY", pd->blank_lines);
    01896               pd->blank_lines=0;
    01897             }
    01898           else;
    01899         }
    01900       else
    01901         {
    01902           pd->blank_lines++;
    01903         }
    01904
    01905       if (pd->do_cret)
    01906         {
    01907           /*
    01908            * 4-level (CRet) dithers...
    01909            */
    01910           if (strcmp(print_mode, "BW") == 0)
    01911             {
    01912               (*(pd->writefunc))(v, black + height / 2, height / 2, 0);
    01913               (*(pd->writefunc))(v, black, height / 2, 1);
    01914             }
    01915           else
    01916             {
    01917               if(pd->do_cretb)
    01918                 {
    01919                   /*        (*(pd->writefunc))(v, black + height / 2, 0, 0); */
    01920                   (*(pd->writefunc))(v, black, height/2, 0);
    01921                 }
    01922               else
    01923                 {
    01924                   (*(pd->writefunc))(v, black + height / 2, height / 2, 0);
    01925                   (*(pd->writefunc))(v, black, height / 2, 0);
    01926                 }
    01927               (*(pd->writefunc))(v, cyan + height / 2, height / 2, 0);
    01928               (*(pd->writefunc))(v, cyan, height / 2, 0);
    01929               (*(pd->writefunc))(v, magenta + height / 2, height / 2, 0);
    01930               (*(pd->writefunc))(v, magenta, height / 2, 0);
    01931               (*(pd->writefunc))(v, yellow + height / 2, height / 2, 0);
    01932               if (pd->do_6color)
    01933                 {
    01934                   (*(pd->writefunc))(v, yellow, height / 2, 0);
    01935                   (*(pd->writefunc))(v, lcyan + height / 2, height / 2, 0);
    01936                   (*(pd->writefunc))(v, lcyan, height / 2, 0);
    01937                   (*(pd->writefunc))(v, lmagenta + height / 2, height / 2, 0);
    01938                   (*(pd->writefunc))(v, lmagenta, height / 2, 1);               /* Last plane set on light magenta */
    01939                 }
    01940               else
    01941                 (*(pd->writefunc))(v, yellow, height / 2, 1);           /* Last plane set on yellow */
    01942             }
    01943         }
    01944       else
    01945         {
    01946           /*
    01947            * Standard 2-level dithers...
    01948            */
    01949
    01950           if (strcmp(print_mode, "BW") == 0)
    01951             {
    01952               (*(pd->writefunc))(v, black, height, 1);
    01953             }
    01954           else
    01955             {
    01956               if (black != NULL)
    01957                 (*(pd->writefunc))(v, black, height, 0);
    01958               (*(pd->writefunc))(v, cyan, height, 0);
    01959               (*(pd->writefunc))(v, magenta, height, 0);
    01960               if (pd->do_6color)
    01961                 {
    01962                   (*(pd->writefunc))(v, yellow, height, 0);
    01963                   (*(pd->writefunc))(v, lcyan, height, 0);
    01964                   (*(pd->writefunc))(v, lmagenta, height, 1);           /* Last plane set on light magenta */
    01965                 }
    01966               else
    01967                 (*(pd->writefunc))(v, yellow, height, 1);               /* Last plane set on yellow */
    01968             }
    01969         }
    01970     }
    01971 }
    01972
    01973 static double
    01974 get_double_param(stp_vars_t *v, const char *param)
    01975 {
    01976   if (param && stp_check_float_parameter(v, param, STP_PARAMETER_ACTIVE))
    01977     return stp_get_float_parameter(v, param);
    01978   else
    01979     return 1.0;
    01980 }
    01981
    01982 static int
    01983 pcl_do_print(stp_vars_t *v, stp_image_t *image)
    01984 {
    01985   int i;
    01986   pcl_privdata_t privdata;
    01987   int           status = 1;
    01988   int           model = stp_get_model_id(v);
    01989   const char    *resolution = stp_get_string_parameter(v, "Resolution");
    01990   const char    *media_size = stp_get_string_parameter(v, "PageSize");
    01991   const char    *media_type = stp_get_string_parameter(v, "MediaType");
    01992   const char    *media_source = stp_get_string_parameter(v, "InputSlot");
    01993   const char    *ink_type = stp_get_string_parameter(v, "InkType");
    01994   const char    *print_mode = stp_get_string_parameter(v, "PrintingMode");
    01995   const char    *duplex_mode = stp_get_string_parameter(v, "Duplex");
    01996   int           page_number = stp_get_int_parameter(v, "PageNumber");
    01997   int           printing_color = 0;
    01998   int           top = stp_get_top(v);
    01999   int           left = stp_get_left(v);
    02000   int           y;              /* Looping vars */
    02001   int           xdpi, ydpi;     /* Resolution */
    02002   unsigned char *black,         /* Black bitmap data */
    02003                 *cyan,          /* Cyan bitmap data */
    02004                 *magenta,       /* Magenta bitmap data */
    02005                 *yellow,        /* Yellow bitmap data */
    02006                 *lcyan,         /* Light Cyan bitmap data */
    02007                 *lmagenta;      /* Light Magenta bitmap data */
    02008   int           page_width,     /* Width of page */
    02009                 page_height,    /* Height of page */
    02010                 page_left,
    02011                 page_top,
    02012                 page_right,
    02013                 page_bottom,
    02014                 out_width,      /* Width of image on page */
    02015                 out_height,     /* Height of image on page */
    02016                 out_channels,   /* Output bytes per pixel */
    02017                 errdiv,         /* Error dividend */
    02018                 errmod,         /* Error modulus */
    02019                 errval,         /* Current error value */
    02020                 errline,        /* Current raster line */
    02021                 errlast;        /* Last raster line loaded */
    02022   unsigned      zero_mask;
    02023   int           image_height,
    02024                 image_width;
    02025   const pcl_cap_t *caps;                /* Printer capabilities */
    02026   int           planes = 3;     /* # of output planes */
    02027   int           pcl_media_size; /* PCL media size code */
    02028   const double *dot_sizes_use;
    02029   const stp_papersize_t *pp;
    02030   int           the_top_margin, /* Corrected top margin */
    02031                 the_left_margin;        /* Corrected left margin */
    02032   stp_curve_t   *lum_adjustment;
    02033   stp_curve_t   *hue_adjustment;
    02034   double density;
    02035
    02036   if (!stp_verify(v))
    02037     {
    02038       stp_eprintf(v, "Print options not verified; cannot print.\n");
    02039       return 0;
    02040     }
    02041   if (strcmp(print_mode, "Color") == 0)
    02042     printing_color = 1;
    02043
    02044   caps = pcl_get_model_capabilities(model);
    02045
    02046  /*
    02047   * Setup a read-only pixel region for the entire image...
    02048   */
    02049
    02050   stp_image_init(image);
    02051   image_height = stp_image_height(image);
    02052   image_width = stp_image_width(image);
    02053
    02054  /*
    02055   * Figure out the output resolution...
    02056   */
    02057
    02058   xdpi = 0;
    02059   ydpi = 0;
    02060   if (resolution)
    02061     {
    02062       for (i = 0; i < NUM_RESOLUTIONS; i++)
    02063         {
    02064           if (!strcmp(resolution, pcl_resolutions[i].pcl_name))
    02065             {
    02066               xdpi = pcl_resolutions[i].p0;
    02067               ydpi = pcl_resolutions[i].p1;
    02068               break;
    02069             }
    02070         }
    02071     }
    02072
    02073   stp_deprintf(STP_DBG_PCL,"pcl: resolution=%dx%d\n",xdpi,ydpi);
    02074   if (xdpi == 0 || ydpi == 0)
    02075     return 0;
    02076
    02077  /*
    02078   * Choose the correct color conversion function...
    02079   */
    02080   if (((caps->resolutions & PCL_RES_600_600_MONO) == PCL_RES_600_600_MONO) &&
    02081       printing_color && xdpi == 600 && ydpi == 600)
    02082     {
    02083       stp_eprintf(v, "600x600 resolution only available in MONO\n");
    02084       stp_set_string_parameter(v, "PrintingMode", "BW");
    02085       printing_color = 0;
    02086     }
    02087
    02088   privdata.do_cret = (xdpi >= 300 &&
    02089              ((caps->color_type & PCL_COLOR_CMYK4) == PCL_COLOR_CMYK4));
    02090   privdata.do_cretb = (xdpi >= 600 && ydpi >= 600 &&
    02091               ((caps->color_type & PCL_COLOR_CMYK4b) == PCL_COLOR_CMYK4b) &&
    02092               printing_color);
    02093   if (privdata.do_cretb){
    02094     privdata.do_cret = 1;
    02095     dot_sizes_use=dot_sizes_cret;
    02096   }else{
    02097     dot_sizes_use=dot_sizes;
    02098   }
    02099
    02100   stp_deprintf(STP_DBG_PCL, "privdata.do_cret = %d\n", privdata.do_cret);
    02101   stp_deprintf(STP_DBG_PCL, "privdata.do_cretb = %d\n", privdata.do_cretb);
    02102
    02103   if (ink_type)
    02104     privdata.do_6color = (strcmp(ink_type, "Photo") == 0);
    02105   else
    02106     privdata.do_6color = 0;
    02107
    02108   stp_deprintf(STP_DBG_PCL, "privdata.do_6color = %d\n", privdata.do_6color);
    02109
    02110  /*
    02111   * Compute the output size...
    02112   */
    02113
    02114   out_width = stp_get_width(v);
    02115   out_height = stp_get_height(v);
    02116
    02117   internal_imageable_area(v, 0, &page_left, &page_right,
    02118                           &page_bottom, &page_top);
    02119   left -= page_left;
    02120   top -= page_top;
    02121   page_width = page_right - page_left;
    02122   page_height = page_bottom - page_top;
    02123
    02124   image_height = stp_image_height(image);
    02125   image_width = stp_image_width(image);
    02126
    02127  /*
    02128   * Set media size here because it is needed by the margin calculation code.
    02129   */
    02130
    02131   if (!media_size)
    02132     media_size = "";
    02133   if (strlen(media_size) == 0 &&
    02134       ((pp = stp_get_papersize_by_size(stp_get_page_height(v),
    02135                                        stp_get_page_width(v))) != NULL))
    02136     media_size = pp->name;
    02137
    02138   pcl_media_size = pcl_convert_media_size(media_size, model);
    02139
    02140   stp_deprintf(STP_DBG_PCL,"pcl_media_size = %d, media_size = %s\n", pcl_media_size, media_size);
    02141
    02142  /*
    02143   * If the media size requested is unknown, try it as a custom size.
    02144   *
    02145   * Warning: The margins may need to be fixed for this!
    02146   */
    02147
    02148   if (pcl_media_size == -1) {
    02149     stp_deprintf(STP_DBG_PCL, "Paper size %s is not directly supported by printer.\n",
    02150       media_size);
    02151     stp_deprintf(STP_DBG_PCL, "Trying as custom pagesize (watch the margins!)\n");
    02152     pcl_media_size = PCL_PAPERSIZE_CUSTOM;                      /* Custom */
    02153   }
    02154
    02155   stp_deprintf(STP_DBG_PCL, "Duplex: %s, Page_Number: %d\n", duplex_mode, page_number);
    02156   privdata.duplex=0;
    02157   privdata.tumble=0;
    02158
    02159  /*
    02160   * Duplex
    02161   */
    02162
    02163   if (duplex_mode)
    02164     {
    02165       if (caps->stp_printer_type & PCL_PRINTER_DUPLEX)
    02166         {
    02167           if ((strcmp(duplex_mode, "DuplexTumble") == 0) || (strcmp(duplex_mode, "DuplexNoTumble") == 0))
    02168             privdata.duplex=1;
    02169           if ((strcmp(duplex_mode, "DuplexTumble") == 0))
    02170             privdata.tumble=1;
    02171         }
    02172       else
    02173         stp_erprintf("pcl: cannot duplex on this hardware.\n");
    02174     }
    02175
    02176  /*
    02177   * Send PCL initialization commands...
    02178   */
    02179
    02180   if ((privdata.duplex == 0) || ((page_number & 1) == 0))
    02181     {
    02182       int pcl_media_type,       /* PCL media type code */
    02183           pcl_media_source;     /* PCL media source code */
    02184
    02185       stp_deprintf(STP_DBG_PCL, "Normal init\n");
    02186
    02187       if (privdata.do_cretb)
    02188         stp_puts("\033*rbC", v);        /* End raster graphics */
    02189       stp_puts("\033E", v);                             /* PCL reset */
    02190       if (privdata.do_cretb)
    02191         stp_zprintf(v, "\033%%-12345X@PJL ENTER LANGUAGE=PCL3GUI\n");
    02192
    02193       stp_puts("\033&l6D\033&k12H",v);          /* 6 lines per inch, 10 chars per inch */
    02194       stp_puts("\033&l0O",v);                   /* Portrait */
    02195
    02196       stp_zprintf(v, "\033&l%dA", pcl_media_size);      /* Set media size we calculated above */
    02197       stp_zprintf(v, "\033&l%dP", stp_get_page_height(v) / 12);
    02198                                                 /* Length of "forms" in "lines" */
    02199       stp_puts("\033&l0L", v);                  /* Turn off perforation skip */
    02200       stp_puts("\033&l0E", v);                  /* Reset top margin to 0 */
    02201
    02202  /*
    02203   * Convert media source string to the code, if specified.
    02204   */
    02205
    02206       if (media_source && strlen(media_source) != 0) {
    02207         pcl_media_source = pcl_string_to_val(media_source, pcl_media_sources,
    02208                              sizeof(pcl_media_sources) / sizeof(pcl_t));
    02209
    02210         stp_deprintf(STP_DBG_PCL,"pcl_media_source = %d, media_source = %s\n", pcl_media_source,
    02211                media_source);
    02212
    02213         if (pcl_media_source == -1)
    02214           stp_deprintf(STP_DBG_PCL, "Unknown media source %s, ignored.\n", media_source);
    02215         else if (pcl_media_source != PCL_PAPERSOURCE_STANDARD) {
    02216
    02217 /* Correct the value by taking the modulus */
    02218
    02219           pcl_media_source = pcl_media_source % PAPERSOURCE_MOD;
    02220           stp_zprintf(v, "\033&l%dH", pcl_media_source);
    02221         }
    02222       }
    02223
    02224  /*
    02225   * Convert media type string to the code, if specified.
    02226   */
    02227
    02228       if (media_type && strlen(media_type) != 0) {
    02229         pcl_media_type = pcl_string_to_val(media_type, pcl_media_types,
    02230                            sizeof(pcl_media_types) / sizeof(pcl_t));
    02231
    02232         stp_deprintf(STP_DBG_PCL,"pcl_media_type = %d, media_type = %s\n", pcl_media_type,
    02233                media_type);
    02234
    02235         if (pcl_media_type == -1) {
    02236           stp_deprintf(STP_DBG_PCL, "Unknown media type %s, set to PLAIN.\n", media_type);
    02237           pcl_media_type = PCL_PAPERTYPE_PLAIN;
    02238         }
    02239
    02240 /*
    02241  * The HP812C doesn't like glossy paper being selected when using 600x600
    02242  * C-RET (PhotoRET II). So we use Premium paper instead.
    02243  *
    02244  */
    02245
    02246         if (privdata.do_cretb && pcl_media_type == PCL_PAPERTYPE_GLOSSY) {
    02247           stp_deprintf(STP_DBG_PCL, "Media type GLOSSY, set to PREMIUM for PhotoRET II.\n");
    02248           pcl_media_type = PCL_PAPERTYPE_PREMIUM;
    02249         }
    02250       }
    02251       else
    02252         pcl_media_type = PCL_PAPERTYPE_PLAIN;
    02253
    02254  /*
    02255   * Set DJ print quality to "best" if resolution >= 300
    02256   */
    02257
    02258       if ((xdpi >= 300) && ((caps->stp_printer_type & PCL_PRINTER_DJ) == PCL_PRINTER_DJ))
    02259       {
    02260         if ((caps->stp_printer_type & PCL_PRINTER_MEDIATYPE) == PCL_PRINTER_MEDIATYPE)
    02261         {
    02262           stp_puts("\033*o1M", v);                      /* Quality = presentation */
    02263           stp_zprintf(v, "\033&l%dM", pcl_media_type);
    02264         }
    02265         else
    02266         {
    02267           stp_puts("\033*r2Q", v);                      /* Quality (high) */
    02268           stp_puts("\033*o2Q", v);                      /* Shingling (4 passes) */
    02269
    02270  /* Depletion depends on media type and cart type. */
    02271
    02272           if ((pcl_media_type == PCL_PAPERTYPE_PLAIN)
    02273            || (pcl_media_type == PCL_PAPERTYPE_BOND)) {
    02274             if ((caps->color_type & PCL_COLOR_CMY) == PCL_COLOR_CMY)
    02275               stp_puts("\033*o2D", v);                  /* Depletion 25% */
    02276             else
    02277               stp_puts("\033*o5D", v);                  /* Depletion 50% with gamma correction */
    02278             }
    02279
    02280           else if ((pcl_media_type == PCL_PAPERTYPE_PREMIUM)
    02281                  || (pcl_media_type == PCL_PAPERTYPE_GLOSSY)
    02282                  || (pcl_media_type == PCL_PAPERTYPE_TRANS))
    02283             stp_puts("\033*o1D", v);                    /* Depletion none */
    02284         }
    02285       }
    02286
    02287 /*
    02288  * Duplex
    02289  */
    02290
    02291       if (privdata.duplex)
    02292           stp_zprintf(v,"\033&l%dS", privdata.duplex + privdata.tumble);
    02293       }
    02294     else
    02295       {
    02296         stp_deprintf(STP_DBG_PCL, "Back face init\n");
    02297         stp_puts("\033&a2G", v);
    02298       }
    02299
    02300 /*
    02301  * See if we need to use the CRD (Configure Raster Data) command, because we're
    02302  * doing something interesting on a DeskJet.
    02303  * (I hate long complicated if statements, the compiler will sort it out!).
    02304  */
    02305
    02306   privdata.use_crd = 0;
    02307   if ((caps->stp_printer_type & PCL_PRINTER_DJ) == PCL_PRINTER_DJ)
    02308     {
    02309     if (xdpi != ydpi)                           /* Different X and Y Resolutions */
    02310       privdata.use_crd = 1;
    02311     if (privdata.do_cret)                       /* Resolution Enhancement */
    02312       privdata.use_crd = 1;
    02313     if (privdata.do_6color)                     /* Photo Ink printing */
    02314       privdata.use_crd = 1;
    02315     if (privdata.duplex)                        /* Duplexing */
    02316       privdata.use_crd = 1;
    02317     }
    02318
    02319   if (privdata.use_crd)
    02320                                                 /* Set resolution using CRD */
    02321   {
    02322
    02323 /*
    02324  * If duplexing on a CRD printer, we need to use the (re)load media command.
    02325  */
    02326
    02327     if (privdata.duplex)
    02328       stp_puts("\033&l-2H",v);                  /* Load media */
    02329
    02330    /*
    02331     * Send configure image data command with horizontal and
    02332     * vertical resolutions as well as a color count...
    02333     */
    02334
    02335     if (printing_color)
    02336       if ((caps->color_type & PCL_COLOR_CMY) == PCL_COLOR_CMY)
    02337         planes = 3;
    02338       else
    02339         if (privdata.do_6color)
    02340           planes = 6;
    02341         else
    02342           planes = 4;
    02343     else
    02344       planes = 1;
    02345
    02346     stp_zprintf(v, "\033*g%dW", 2 + (planes * 6));
    02347     stp_putc(2, v);                             /* Format 2 (Complex Direct Planar) */
    02348     stp_putc(planes, v);                                /* # output planes */
    02349
    02350     if (planes != 3) {          /* Black resolution */
    02351       stp_send_command(v, "", "HHH", xdpi, ydpi, (privdata.do_cretb || !privdata.do_cret) ? 2 : 4);
    02352     }
    02353
    02354     if (planes != 1) {          /* Cyan, magenta, yellow resolutions */
    02355       stp_send_command(v, "", "HHH", xdpi, ydpi, privdata.do_cret ? 4 : 2);
    02356       stp_send_command(v, "", "HHH", xdpi, ydpi, privdata.do_cret ? 4 : 2);
    02357       stp_send_command(v, "", "HHH", xdpi, ydpi, privdata.do_cret ? 4 : 2);
    02358     }
    02359     if (planes == 6)            /* LC, LM resolutions */
    02360     {
    02361       stp_send_command(v, "", "HHH", xdpi, ydpi, privdata.do_cret ? 4 : 2);
    02362       stp_send_command(v, "", "HHH", xdpi, ydpi, privdata.do_cret ? 4 : 2);
    02363     }
    02364   }
    02365   else
    02366   {
    02367     stp_zprintf(v, "\033*t%dR", xdpi);          /* Simple resolution */
    02368     if (printing_color)
    02369     {
    02370       if ((caps->color_type & PCL_COLOR_CMY) == PCL_COLOR_CMY)
    02371         stp_puts("\033*r-3U", v);               /* Simple CMY color */
    02372       else
    02373         stp_puts("\033*r-4U", v);               /* Simple KCMY color */
    02374     }
    02375   }
    02376
    02377 #ifndef PCL_DEBUG_DISABLE_COMPRESSION
    02378   if ((caps->stp_printer_type & PCL_PRINTER_TIFF) == PCL_PRINTER_TIFF)
    02379   {
    02380     stp_puts("\033*b2M", v);                    /* Mode 2 (TIFF) */
    02381   }
    02382   else
    02383 #endif
    02384   {
    02385     stp_puts("\033*b0M", v);                    /* Mode 0 (no compression) */
    02386   }
    02387
    02388  /*
    02389   * Convert image size to printer resolution and setup the page for printing...
    02390   */
    02391
    02392   out_width  = xdpi * out_width / 72;
    02393   out_height = ydpi * out_height / 72;
    02394
    02395   if (pcl_media_size == PCL_PAPERSIZE_A4)
    02396   {
    02397     the_left_margin = caps->a4_margins.left_margin;
    02398     the_top_margin = caps->a4_margins.top_margin;
    02399   }
    02400   else
    02401   {
    02402     the_left_margin = caps->normal_margins.left_margin;
    02403     the_top_margin = caps->normal_margins.top_margin;
    02404   }
    02405
    02406   stp_deprintf(STP_DBG_PCL, "left %d margin %d top %d margin %d width %d height %d\n",
    02407           left, the_left_margin, top, the_top_margin, out_width, out_height);
    02408
    02409   if (!privdata.do_cretb) {
    02410     stp_zprintf(v, "\033&a%dH", 10 * left);             /* Set left raster position */
    02411     stp_zprintf(v, "\033&a%dV", 10 * (top + the_top_margin));
    02412                                 /* Set top raster position */
    02413   }
    02414   stp_zprintf(v, "\033*r%dS", out_width);               /* Set raster width */
    02415   stp_zprintf(v, "\033*r%dT", out_height);      /* Set raster height */
    02416
    02417   if (privdata.do_cretb)
    02418     {
    02419       /* Move to top left of printed area */
    02420       stp_zprintf(v, "\033*p%dY", (top + the_top_margin)*4); /* Measured in dots. */
    02421       stp_zprintf(v, "\033*p%dX", left*4);
    02422     }
    02423   stp_puts("\033*r1A", v);                      /* Start GFX */
    02424
    02425  /*
    02426   * Allocate memory for the raster data...
    02427   */
    02428
    02429   privdata.height = (out_width + 7) / 8;
    02430   if (privdata.do_cret)
    02431     privdata.height *= 2;
    02432
    02433   if (!printing_color)
    02434   {
    02435     black   = stp_malloc(privdata.height);
    02436     cyan    = NULL;
    02437     magenta = NULL;
    02438     yellow  = NULL;
    02439     lcyan    = NULL;
    02440     lmagenta = NULL;
    02441   }
    02442   else
    02443   {
    02444     cyan    = stp_malloc(privdata.height);
    02445     magenta = stp_malloc(privdata.height);
    02446     yellow  = stp_malloc(privdata.height);
    02447
    02448     if ((caps->color_type & PCL_COLOR_CMY) == PCL_COLOR_CMY)
    02449       black = NULL;
    02450     else
    02451       black = stp_malloc(privdata.height);
    02452     if (privdata.do_6color)
    02453     {
    02454       lcyan    = stp_malloc(privdata.height);
    02455       lmagenta = stp_malloc(privdata.height);
    02456     }
    02457     else
    02458     {
    02459       lcyan    = NULL;
    02460       lmagenta = NULL;
    02461     }
    02462   }
    02463
    02464   if (black)
    02465     {
    02466       if (cyan)
    02467         stp_set_string_parameter(v, "STPIOutputType", "KCMY");
    02468       else
    02469         stp_set_string_parameter(v, "STPIOutputType", "Grayscale");
    02470     }
    02471   else
    02472     stp_set_string_parameter(v, "STPIOutputType", "CMY");
    02473
    02474 /* Allocate buffer for pcl_mode2 tiff compression */
    02475
    02476 #ifndef PCL_DEBUG_DISABLE_COMPRESSION
    02477   if ((caps->stp_printer_type & PCL_PRINTER_TIFF) == PCL_PRINTER_TIFF)
    02478   {
    02479     privdata.comp_buf = stp_malloc((privdata.height + 128 + 7) * 129 / 128);
    02480     privdata.writefunc = pcl_mode2;
    02481   }
    02482   else
    02483 #endif
    02484   {
    02485     privdata.comp_buf = NULL;
    02486     privdata.writefunc = pcl_mode0;
    02487   }
    02488
    02489 /* Set up dithering for special printers. */
    02490
    02491 #if 1           /* Leave alone for now */
    02492   if (!stp_check_float_parameter(v, "GCRLower", STP_PARAMETER_ACTIVE))
    02493     stp_set_default_float_parameter(v, "GCRLower", .3);
    02494   if (!stp_check_float_parameter(v, "GCRUpper", STP_PARAMETER_ACTIVE))
    02495     stp_set_default_float_parameter(v, "GCRUpper", .999);
    02496 #endif
    02497   stp_dither_init(v, image, out_width, xdpi, ydpi);
    02498
    02499   if (black)
    02500     stp_dither_add_channel(v, black, STP_ECOLOR_K, 0);
    02501   if (cyan)
    02502     stp_dither_add_channel(v, cyan, STP_ECOLOR_C, 0);
    02503   if (lcyan)
    02504     stp_dither_add_channel(v, lcyan, STP_ECOLOR_C, 1);
    02505   if (magenta)
    02506     stp_dither_add_channel(v, magenta, STP_ECOLOR_M, 0);
    02507   if (lmagenta)
    02508     stp_dither_add_channel(v, lmagenta, STP_ECOLOR_M, 1);
    02509   if (yellow)
    02510     stp_dither_add_channel(v, yellow, STP_ECOLOR_Y, 0);
    02511
    02512 /* Ensure that density does not exceed 1.0 */
    02513
    02514   if (!stp_check_float_parameter(v, "Density", STP_PARAMETER_DEFAULTED))
    02515     {
    02516       stp_set_float_parameter_active(v, "Density", STP_PARAMETER_ACTIVE);
    02517       stp_set_float_parameter(v, "Density", 1.0);
    02518     }
    02519
    02520   stp_deprintf(STP_DBG_PCL, "Density: %f\n", stp_get_float_parameter(v, "Density"));
    02521   if (stp_get_float_parameter(v, "Density") > 1.0)
    02522     stp_set_float_parameter(v, "Density", 1.0);
    02523   density = stp_get_float_parameter(v, "Density");
    02524
    02525   if (privdata.do_cret)                 /* 4-level printing for 800/1120 */
    02526     {
    02527       stp_dither_set_inks_simple(v, STP_ECOLOR_Y, 3, dot_sizes_use, 1.0, 0.08);
    02528       if (!privdata.do_cretb)
    02529         stp_dither_set_inks_simple(v, STP_ECOLOR_K, 3, dot_sizes_use, 1.0, 1.0);
    02530
    02531       /* Note: no printer I know of does both CRet (4-level) and 6 colour, but
    02532          what the heck. variable_dither_ranges copied from print-escp2.c */
    02533
    02534       if (privdata.do_6color)                   /* Photo for 69x */
    02535         {
    02536           stp_dither_set_inks_full(v, STP_ECOLOR_C, 6, variable_shades, 1.0,
    02537                                     0.31 / .5);
    02538           stp_dither_set_inks_full(v, STP_ECOLOR_M, 6, variable_shades, 1.0,
    02539                                     0.61 / .97);
    02540         }
    02541       else
    02542         {
    02543           stp_dither_set_inks_simple(v, STP_ECOLOR_C, 3, dot_sizes_use, 1.0,
    02544                                       0.31 / .5);
    02545           stp_dither_set_inks_simple(v, STP_ECOLOR_M, 3, dot_sizes_use, 1.0,
    02546                                       0.61 / .7);
    02547         }
    02548     }
    02549   else if (privdata.do_6color)
    02550     {
    02551       /* Set light inks for 6 colour printers.
    02552          Numbers copied from print-escp2.c */
    02553       stp_dither_set_inks_full(v, STP_ECOLOR_C, 2, photo_dither_shades, 1.0,
    02554                                 0.31 / .5);
    02555       stp_dither_set_inks_full(v, STP_ECOLOR_M, 2, photo_dither_shades, 1.0,
    02556                                 0.61 / .7);
    02557     }
    02558   if (black)
    02559     stp_channel_set_density_adjustment(v, STP_ECOLOR_K, 0,
    02560                                        get_double_param(v, "BlackDensity") *
    02561                                        get_double_param(v, "Density"));
    02562   if (cyan)
    02563     stp_channel_set_density_adjustment(v, STP_ECOLOR_C, 0,
    02564                                        get_double_param(v, "CyanDensity") *
    02565                                        get_double_param(v, "Density"));
    02566   if (magenta)
    02567     stp_channel_set_density_adjustment(v, STP_ECOLOR_M, 0,
    02568                                        get_double_param(v, "MagentaDensity") *
    02569                                        get_double_param(v, "Density"));
    02570   if (yellow)
    02571     stp_channel_set_density_adjustment(v, STP_ECOLOR_Y, 0,
    02572                                         get_double_param(v, "YellowDensity") *
    02573                                         get_double_param(v, "Density"));
    02574   if (lcyan)
    02575     stp_channel_set_density_adjustment
    02576       (v, STP_ECOLOR_C, 1, (get_double_param(v, "CyanDensity") *
    02577                         get_double_param(v, "LightCyanTransition") *
    02578                         get_double_param(v, "Density")));
    02579   if (lmagenta)
    02580     stp_channel_set_density_adjustment
    02581       (v, STP_ECOLOR_M, 1, (get_double_param(v, "MagentaDensity") *
    02582                         get_double_param(v, "LightMagentaTransition") *
    02583                         get_double_param(v, "Density")));
    02584
    02585
    02586   if (!stp_check_curve_parameter(v, "HueMap", STP_PARAMETER_ACTIVE))
    02587     {
    02588       hue_adjustment = stp_curve_create_from_string(standard_hue_adjustment);
    02589       stp_set_curve_parameter(v, "HueMap", hue_adjustment);
    02590       stp_curve_destroy(hue_adjustment);
    02591     }
    02592   if (!stp_check_curve_parameter(v, "LumMap", STP_PARAMETER_ACTIVE))
    02593     {
    02594       lum_adjustment = stp_curve_create_from_string(standard_lum_adjustment);
    02595       stp_curve_destroy(lum_adjustment);
    02596     }
    02597
    02598   out_channels = stp_color_init(v, image, 65536);
    02599
    02600   errdiv  = image_height / out_height;
    02601   errmod  = image_height % out_height;
    02602   errval  = 0;
    02603   errlast = -1;
    02604   errline  = 0;
    02605   privdata.blank_lines = 0;
    02606 #ifndef PCL_DEBUG_DISABLE_BLANKLINE_REMOVAL
    02607   privdata.do_blank = ((caps->stp_printer_type & PCL_PRINTER_BLANKLINE) ==
    02608                        PCL_PRINTER_BLANKLINE);
    02609 #else
    02610   privdata.do_blank = 0;
    02611 #endif
    02612   stp_allocate_component_data(v, "Driver", NULL, NULL, &privdata);
    02613
    02614   for (y = 0; y < out_height; y ++)
    02615   {
    02616     int duplicate_line = 1;
    02617     if (errline != errlast)
    02618     {
    02619       errlast = errline;
    02620       duplicate_line = 0;
    02621       if (stp_color_get_row(v, image, errline, &zero_mask))
    02622         {
    02623           status = 2;
    02624           break;
    02625         }
    02626     }
    02627     stp_dither(v, y, duplicate_line, zero_mask, NULL);
    02628     pcl_printfunc(v);
    02629     stp_deprintf(STP_DBG_PCL,"pcl_print: y = %d, line = %d, val = %d, mod = %d, height = %d\n",
    02630                   y, errline, errval, errmod, out_height);
    02631     errval += errmod;
    02632     errline += errdiv;
    02633     if (errval >= out_height)
    02634     {
    02635       errval -= out_height;
    02636       errline ++;
    02637     }
    02638   }
    02639
    02640 /* Output trailing blank lines (may not be required?) */
    02641
    02642   if (privdata.blank_lines > 1)
    02643   {
    02644     privdata.blank_lines--;             /* correct for one already output */
    02645     stp_deprintf(STP_DBG_PCL, "Blank Lines = %d\n", privdata.blank_lines);
    02646     stp_zprintf(v, "\033*b%dY", privdata.blank_lines);
    02647     privdata.blank_lines=0;
    02648   }
    02649
    02650   stp_image_conclude(image);
    02651
    02652  /*
    02653   * Cleanup...
    02654   */
    02655
    02656   if (black != NULL)
    02657     stp_free(black);
    02658   if (cyan != NULL)
    02659   {
    02660     stp_free(cyan);
    02661     stp_free(magenta);
    02662     stp_free(yellow);
    02663   }
    02664   if (lcyan != NULL)
    02665   {
    02666     stp_free(lcyan);
    02667     stp_free(lmagenta);
    02668   }
    02669
    02670   if (privdata.comp_buf != NULL)
    02671     stp_free(privdata.comp_buf);
    02672
    02673   if ((caps->stp_printer_type & PCL_PRINTER_NEW_ERG) == PCL_PRINTER_NEW_ERG)
    02674     stp_puts("\033*rC", v);
    02675   else
    02676     stp_puts("\033*rB", v);
    02677
    02678   if ((privdata.duplex == 1) && ((page_number & 1) == 0))
    02679       stp_puts("\014", v);              /* Form feed */
    02680   else
    02681     {
    02682       stp_puts("\033&l0H", v);          /* Eject page */
    02683       if (privdata.do_cretb)
    02684         stp_zprintf(v, "\033%%-12345X\n");
    02685       stp_puts("\033E", v);             /* PCL reset */
    02686     }
    02687   return status;
    02688 }
    02689
    02690 static int
    02691 pcl_print(const stp_vars_t *v, stp_image_t *image)
    02692 {
    02693   int status;
    02694   stp_vars_t *nv = stp_vars_create_copy(v);
    02695   stp_prune_inactive_options(nv);
    02696   status = pcl_do_print(nv, image);
    02697   stp_vars_destroy(nv);
    02698   return status;
    02699 }
    02700
    02701 static const stp_printfuncs_t print_pcl_printfuncs =
    02702 {
    02703   pcl_list_parameters,
    02704   pcl_parameters,
    02705   stp_default_media_size,
    02706   pcl_imageable_area,
    02707   pcl_limit,
    02708   pcl_print,
    02709   pcl_describe_resolution,
    02710   pcl_describe_output,
    02711   stp_verify_printer_params,
    02712   NULL,
    02713   NULL
    02714 };
    02715
    02716
    02717 /*
    02718  * 'pcl_mode0()' - Send PCL graphics using mode 0 (no) compression.
    02719  */
    02720
    02721 static void
    02722 pcl_mode0(stp_vars_t *v,                /* I - Print file or command */
    02723           unsigned char *line,          /* I - Output bitmap data */
    02724           int           height,         /* I - Height of bitmap data */
    02725           int           last_plane)     /* I - True if this is the last plane */
    02726 {
    02727   stp_zprintf(v, "\033*b%d%c", height, last_plane ? 'W' : 'V');
    02728   stp_zfwrite((const char *) line, height, 1, v);
    02729 }
    02730
    02731
    02732 /*
    02733  * 'pcl_mode2()' - Send PCL graphics using mode 2 (TIFF) compression.
    02734  */
    02735
    02736 static void
    02737 pcl_mode2(stp_vars_t *v,                /* I - Print file or command */
    02738           unsigned char *line,          /* I - Output bitmap data */
    02739           int           height,         /* I - Height of bitmap data */
    02740           int           last_plane)     /* I - True if this is the last plane */
    02741 {
    02742   pcl_privdata_t *privdata =
    02743     (pcl_privdata_t *) stp_get_component_data(v, "Driver");
    02744   unsigned char *comp_buf = privdata->comp_buf;
    02745   unsigned char *comp_ptr;              /* Current slot in buffer */
    02746
    02747   stp_pack_tiff(v, line, height, comp_buf, &comp_ptr, NULL, NULL);
    02748
    02749  /*
    02750   * Send a line of raster graphics...
    02751   */
    02752
    02753   stp_zprintf(v, "\033*b%d%c", (int)(comp_ptr - comp_buf), last_plane ? 'W' : 'V');
    02754   stp_zfwrite((const char *)comp_buf, comp_ptr - comp_buf, 1, v);
    02755 }
    02756
    02757
    02758 static stp_family_t print_pcl_module_data =
    02759   {
    02760     &print_pcl_printfuncs,
    02761     NULL
    02762   };
    02763
    02764
    02765 static int
    02766 print_pcl_module_init(void)
    02767 {
    02768   return stp_family_register(print_pcl_module_data.printer_list);
    02769 }
    02770
    02771
    02772 static int
    02773 print_pcl_module_exit(void)
    02774 {
    02775   return stp_family_unregister(print_pcl_module_data.printer_list);
    02776 }
    02777
    02778
    02779 /* Module header */
    02780 #define stp_module_version print_pcl_LTX_stp_module_version
    02781 #define stp_module_data print_pcl_LTX_stp_module_data
    02782
    02783 stp_module_version_t stp_module_version = {0, 0};
    02784
    02785 stp_module_t stp_module_data =
    02786   {
    02787     "pcl",
    02788     VERSION,
    02789     "PCL family driver",
    02790     STP_MODULE_CLASS_FAMILY,
    02791     NULL,
    02792     print_pcl_module_init,
    02793     print_pcl_module_exit,
    02794     (void *) &print_pcl_module_data
    02795   };
    02796