~ubuntu-branches/ubuntu/oneiric/ghostscript/oneiric

« back to all changes in this revision

Viewing changes to contrib/gdevlx32.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2011-07-15 16:49:55 UTC
  • mfrom: (1.1.23 upstream)
  • Revision ID: james.westby@ubuntu.com-20110715164955-uga6qibao6kez05c
Tags: 9.04~dfsg~20110715-0ubuntu1
* New upstream release
   - GIT snapshot from Jult, 12 2011.
* debian/patches/020110406~a54df2d.patch,
  debian/patches/020110408~0791cc8.patch,
  debian/patches/020110408~507cbee.patch,
  debian/patches/020110411~4509a49.patch,
  debian/patches/020110412~78bb9a6.patch,
  debian/patches/020110418~a05ab8a.patch,
  debian/patches/020110420~20b6c78.patch,
  debian/patches/020110420~4ddefa2.patch: Removed upstream patches.
* debian/rules: Generate ABI version number (variable "abi") correctly,
  cutting off repackaging and pre-release parts.
* debian/rules: Added ./lcms2/ directory to DEB_UPSTREAM_REPACKAGE_EXCLUDES.
* debian/copyright: Added lcms2/* to the list of excluded files.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 *
4
4
 * version 0.4.1
5
5
 *
6
 
 * Copyright 2000 by Daniel Gordini (dgordin@tin.it) 
 
6
 * Copyright 2000 by Daniel Gordini (dgordin@tin.it)
7
7
 *
8
8
 * --------------------------------------------------------------------
9
9
 *
20
20
 * You should have received a copy of the GNU General Public License
21
21
 * along with this program; if not, write to the Free Software
22
22
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
 
 * 
 
23
 *
24
24
 * --------------------------------------------------------------------
25
25
 *
26
26
 * This driver is almost 100% original code but it is based
27
 
 * on protocol information partly discovered by Andrew Onifer III 
28
 
 * (http://www.mindspring.com/~aonifer) and Peter B. West 
29
 
 * (http://www.powerup.com.au/~pbwest) that were used as a starting 
 
27
 * on protocol information partly discovered by Andrew Onifer III
 
28
 * (http://www.mindspring.com/~aonifer) and Peter B. West
 
29
 * (http://www.powerup.com.au/~pbwest) that were used as a starting
30
30
 * base for the reverse-engineering of the protocol.
31
31
 *
32
32
 * Please mail me bug reports, comments and suggestions.
90
90
#define LXM3200_C  1  /* Standard color mode */
91
91
#define LXM3200_P  2  /* Photo color mode */
92
92
 
93
 
/* Initial horizontal position for the printheads, 
 
93
/* Initial horizontal position for the printheads,
94
94
 * in 1200ths of an inch. Note that "left" and "right"
95
 
 * head here refers to paper margin, and so looking at 
 
95
 * head here refers to paper margin, and so looking at
96
96
 * them from the front of printer they will appear reversed.
97
97
 */
98
98
 
99
99
/* Left head (B&W/photo) start position */
100
100
#define LHSTART (gendata.leftoffset+6254)
101
101
/* added for Lexmark Z12 28.09.2002 */
102
 
#define LHSTART_z12 (gendata.leftoffset+5000) 
 
102
#define LHSTART_z12 (gendata.leftoffset+5000)
103
103
 
104
 
/* Right head (color) start position. This is relative to 
 
104
/* Right head (color) start position. This is relative to
105
105
 * LHSTART so we only need to change one parameter to adjust
106
106
 * the head starting position. In the case of the Lexmark Z12
107
 
 * we have only one cartridge: black or color, so 
 
107
 * we have only one cartridge: black or color, so
108
108
 * LHSTART_Z12 = RHSTART_Z12
109
109
 */
110
110
#define RHSTART (LHSTART-2120)
111
111
#define RHSTART_z12 (LHSTART_z12) /* added for Lexmark Z12 28.9.2002 */
112
112
 
113
 
/* Difference in starting position between left-to-right 
 
113
/* Difference in starting position between left-to-right
114
114
 * and right-to-left passes, in 1200ths of an inch.
115
115
 * Obviously only used in bidirectional mode.
116
116
 */
136
136
 
137
137
/* Offset of color pens from first row, in 1/600ths of an inch.
138
138
 * Pen 0 is the topmost and is the CYAN or LIGHTCYAN pen (depending
139
 
 * on the cartridge: standard color or photo). Pen 1 is the middle 
140
 
 * one, which carries MAGENTA or LIGHTMAGENTA color. Pen 2 is the 
 
139
 * on the cartridge: standard color or photo). Pen 1 is the middle
 
140
 * one, which carries MAGENTA or LIGHTMAGENTA color. Pen 2 is the
141
141
 * bottom one, which is YELLOW or BLACK.
142
142
 */
143
143
#define PEN0OFS  0
144
144
#define PEN1OFS  92
145
 
#define PEN2OFS  184  
 
145
#define PEN2OFS  184
146
146
 
147
147
/* Number of nozzles in each pen type */
148
148
#define COLORPEN 64   /* Each color pen of a color/photo cartridge */
164
164
#define LHDATA 0x02 /* The buffer contains data for the left head */
165
165
#define RHDATA 0x04 /* The buffer contains data for the right head */
166
166
 
167
 
/* Printer's margins, in inches. The Lexmark 3200 has two settings 
168
 
 * for the side margins: one is used with A4-sized paper and one 
169
 
 * (here called conventionally "LETTER") is used for all other paper 
 
167
/* Printer's margins, in inches. The Lexmark 3200 has two settings
 
168
 * for the side margins: one is used with A4-sized paper and one
 
169
 * (here called conventionally "LETTER") is used for all other paper
170
170
 * sizes. Envelopes have different margins as well, but under ghostscript
171
171
 * it's quite hard to know, from inside a printer driver, if we are
172
172
 * printing on envelopes or on standard paper, so we just ignore that.
184
184
#define LXM3200_LETTER_TOPOFFSET   84
185
185
#define LXM3200_LETTER_LEFTOFFSET  300
186
186
 
187
 
 
188
 
/* 
189
 
 * ------ The device descriptor ------ 
 
187
/*
 
188
 * ------ The device descriptor ------
190
189
 */
191
190
 
192
191
/* Device procedures */
193
192
static gx_device_procs lxm3200_procs =
194
193
  prn_color_params_procs(lxm3200_open, gdev_prn_output_page, gdev_prn_close,
195
 
          lxm3200_map_rgb_color, lxm3200_map_color_rgb, lxm3200_get_params, 
196
 
    lxm3200_put_params); 
 
194
          lxm3200_map_rgb_color, lxm3200_map_color_rgb, lxm3200_get_params,
 
195
    lxm3200_put_params);
197
196
 
198
197
/* Define an extension (subclass) of gx_device_printer. */
199
 
typedef struct lxm_device_s 
200
 
201
 
        gx_device_common;
202
 
        gx_prn_device_common;
203
 
        int rendermode;  /* Rendering mode (BW, CMYK, CcMmYK) */     
204
 
        int algnA; /* Horizontal alignment between left and right cartridges */
205
 
        int algnB; /* Vertical alignment between left and right cartridges */
206
 
        int algnC; /* Nozzle column separation of left cartridge */
207
 
        int algnD; /* Nozzle column separation of right cartridge */
208
 
        int bidir;   /* Bidirectional printing active ? */
209
 
        int numpass; /* Number of head passes for each stripe */
210
 
        int leftoffset; /* Offset of first column from left side of paper */
211
 
        int topoffset;  /* Offset of first row from top of paper */
 
198
typedef struct lxm_device_s
 
199
{
 
200
        gx_device_common;
 
201
        gx_prn_device_common;
 
202
        int rendermode;  /* Rendering mode (BW, CMYK, CcMmYK) */
 
203
        int algnA; /* Horizontal alignment between left and right cartridges */
 
204
        int algnB; /* Vertical alignment between left and right cartridges */
 
205
        int algnC; /* Nozzle column separation of left cartridge */
 
206
        int algnD; /* Nozzle column separation of right cartridge */
 
207
        int bidir;   /* Bidirectional printing active ? */
 
208
        int numpass; /* Number of head passes for each stripe */
 
209
        int leftoffset; /* Offset of first column from left side of paper */
 
210
        int topoffset;  /* Offset of first row from top of paper */
212
211
        int model; /* Parameter to choose the model - lxm3200=0, z12=1, z31=2 */
213
212
        int z31m; /* Alignment parameter for the Z31 */
214
213
} lxm_device;
215
214
 
216
215
/* Device definition: Lexmark 3200 */
217
 
lxm_device far_data gs_lxm3200_device = 
 
216
lxm_device far_data gs_lxm3200_device =
218
217
{
219
 
        prn_device_body(lxm_device, 
220
 
                lxm3200_procs, 
221
 
                "lxm3200",
222
 
                DEFAULT_WIDTH_10THS, 
223
 
                DEFAULT_HEIGHT_10THS,
224
 
                600, /* default x dpi */
225
 
                600, /* default y dpi */
226
 
                0.0, /* left margin, inches (filled-in later) */
227
 
                0.0, /* bottom margin, inches (filled-in later) */
228
 
                0.0, /* right margin, inches (filled-in later) */
229
 
                0.0, /* top margin, inches (filled-in later) */
230
 
                1,   /* number of color components (mono) */
231
 
                8,   /* bits per pixel */
232
 
                1,   /* number of gray levels-1: B&W only */
233
 
                0,   /* number of color levels-1: no color */
234
 
                2,   /* dither gray: maximum 2 distinct gray levels */
235
 
                0,   /* dither rgb: no RGB dithering in this mode */
236
 
                lxm3200_print_page),
237
 
        LXM3200_C,      /* default printing mode */
238
 
        16, 8, 16, 16,  /* default aligment parameters value */
239
 
        0, 1,           /* default bidirectional and numpasses value */
240
 
        0, 0,           /* left and top offsets (filled-in later) */
 
218
        prn_device_body(lxm_device,
 
219
                lxm3200_procs,
 
220
                "lxm3200",
 
221
                DEFAULT_WIDTH_10THS,
 
222
                DEFAULT_HEIGHT_10THS,
 
223
                600, /* default x dpi */
 
224
                600, /* default y dpi */
 
225
                0.0, /* left margin, inches (filled-in later) */
 
226
                0.0, /* bottom margin, inches (filled-in later) */
 
227
                0.0, /* right margin, inches (filled-in later) */
 
228
                0.0, /* top margin, inches (filled-in later) */
 
229
                1,   /* number of color components (mono) */
 
230
                8,   /* bits per pixel */
 
231
                1,   /* number of gray levels-1: B&W only */
 
232
                0,   /* number of color levels-1: no color */
 
233
                2,   /* dither gray: maximum 2 distinct gray levels */
 
234
                0,   /* dither rgb: no RGB dithering in this mode */
 
235
                lxm3200_print_page),
 
236
        LXM3200_C,      /* default printing mode */
 
237
        16, 8, 16, 16,  /* default aligment parameters value */
 
238
        0, 1,           /* default bidirectional and numpasses value */
 
239
        0, 0,           /* left and top offsets (filled-in later) */
241
240
        0,     /* default model = Lexmark 3200 */
242
241
        100   /* default z31m */
243
242
};
249
248
static byte ibits[8] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
250
249
 
251
250
/* Lookup table for masking color pens in color/photo cartridges.
252
 
 * This is used to check the raster buffer for the presence of a 
 
251
 * This is used to check the raster buffer for the presence of a
253
252
 * particular color in the pixel we are encoding.
254
253
 * The first index is the head (LEFT or RIGHT) which is used to
255
254
 * distinguish between photo and color cartridges. The second index
257
256
 * lower pen) on that cartridge.
258
257
 */
259
258
static byte colmask[2][3] =
260
 
{       
261
 
        { LIGHTCYAN, LIGHTMAGENTA, BLACK},
262
 
        { CYAN, MAGENTA, YELLOW }
 
259
{
 
260
        { LIGHTCYAN, LIGHTMAGENTA, BLACK},
 
261
        { CYAN, MAGENTA, YELLOW }
263
262
};
264
263
 
265
 
/* Lookup table for pen position offsets of color/photo cartridges. 
 
264
/* Lookup table for pen position offsets of color/photo cartridges.
266
265
 * Parameter is the pen number, as defined by the pen offsets above:
267
 
 * pen 0 is CYAN/LIGHTCYAN, pen 1 is MAGENTA/LIGHTMAGENTA, pen 2 is 
 
266
 * pen 0 is CYAN/LIGHTCYAN, pen 1 is MAGENTA/LIGHTMAGENTA, pen 2 is
268
267
 * YELLOW/BLACK. This is used to properly take account the position
269
 
 * of each color pen relative to the vertical position of the 
 
268
 * of each color pen relative to the vertical position of the
270
269
 * color/photo cartridge.
271
270
 */
272
271
static int penofs[3];
288
287
 
289
288
/* Initialization sequence needed at the beginning of the data stream.
290
289
 * This is invariant and contains a reset sequence, meaning each single
291
 
 * page in a multiple page output is sent to the printer as an independent 
 
290
 * page in a multiple page output is sent to the printer as an independent
292
291
 * print job.
293
292
 */
294
293
static byte init_sequence[] =
295
294
{
296
 
        0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
297
 
        0x1b, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33,
298
 
        0x1b, 0x30, 0x80, 0x0C, 0x02, 0x00, 0x00, 0xbe,
299
 
        0x1b, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21
300
 
};              
 
295
        0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
 
296
        0x1b, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33,
 
297
        0x1b, 0x30, 0x80, 0x0C, 0x02, 0x00, 0x00, 0xbe,
 
298
        0x1b, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21
 
299
};
301
300
 
302
301
static byte z12_init_sequence[] =
303
302
{
309
308
};
310
309
 
311
310
/* General global data that must be accessible
312
 
 * by all routines. 
 
311
 * by all routines.
313
312
 */
314
313
typedef struct pagedata_s
315
314
{
316
 
        /* General invariant data */
317
 
        int numbytes;    /* Number of bytes in a scanline of the buffer */
318
 
        int numrbytes;   /* Width (in bytes) of one rasterized scanline */
319
 
        int goffset;     /* Guard offset at each side of each scanline (columns) */ 
320
 
        int numblines;   /* Number of lines in a buffer */
321
 
        int numlines;    /* Number of lines in a vertical head pass */
322
 
        int rendermode;  /* Type of rendering */
323
 
        int numvlines;   /* Number of lines in the page */
324
 
        int numcols;     /* Number of columns in a row */
325
 
        int numpasses;   /* Number of passes used to print one stripe */
326
 
        int bidirprint;  /* Bidirectional printing enabled ? */
327
 
        int select;      /* Resolution selector */
 
315
        /* General invariant data */
 
316
        int numbytes;    /* Number of bytes in a scanline of the buffer */
 
317
        int numrbytes;   /* Width (in bytes) of one rasterized scanline */
 
318
        int goffset;     /* Guard offset at each side of each scanline (columns) */
 
319
        int numblines;   /* Number of lines in a buffer */
 
320
        int numlines;    /* Number of lines in a vertical head pass */
 
321
        int rendermode;  /* Type of rendering */
 
322
        int numvlines;   /* Number of lines in the page */
 
323
        int numcols;     /* Number of columns in a row */
 
324
        int numpasses;   /* Number of passes used to print one stripe */
 
325
        int bidirprint;  /* Bidirectional printing enabled ? */
 
326
        int select;      /* Resolution selector */
328
327
        int modelprint;  /* which printer? - lxm3200=0, z12=1, z31=2 */
329
328
        int z31margin;   /* margin for the Z31 */
330
329
 
331
 
        /* Printing offsets */
332
 
        int leftoffset;  /* Start printing offset from left margin */
333
 
        int topoffset;   /* Start printing offset from top margin */
334
 
 
335
 
        /* Resolution settings */
336
 
        int xres;        /* Horizontal dots per inch */
337
 
        int yres;        /* Vertical dots per inch */
338
 
        int xrmul;       /* Horizontal coordinate multiplier */
339
 
        int yrmul;       /* Vertical coordinate multiplier */
340
 
        
341
 
        /* Pagewide status */
342
 
        int curheadpos;  /* Current absolute printhead position */
343
 
        int linetoeject; /* Number of lines for the eject command */
344
 
        int direction;   /* Printing direction for next stripe */
345
 
 
346
 
        /* Alignment data */
347
 
        int bwsep;     /* Nozzle columns separation in B&W/photo cartridge */
348
 
        int colsep;    /* Nozzle columns separation in color cartridge */
349
 
        int vertalign; /* Vertical alignment offset of the two cartridges */
350
 
        int lrhalign;  /* Horizontal alignment between left and right cartridges */
351
 
 
352
 
        /* Data pointers */
353
 
        byte *outdata;    /* Buffer to output data codes for one full stripe */
354
 
        byte *scanbuf;    /* Buffer to contain the rasterized scanlines */
355
 
        FILE *stream;     /* Output stream */
356
 
        lxm_device *dev;  /* Pointer to our device */
357
 
 
358
 
        /* Buffer data */
359
 
        int left, right;  /* Actual left and right margins */
360
 
        int firstline;    /* Head of the circular scanline buffer */
361
 
        int lastblack;    /* Line of last black pass rendered in a color print */
362
 
        int curvline;     /* Current vertical position */
363
 
        
364
 
        /* Stripe related data */
365
 
        byte header[24];  /* Stripe header data */
366
 
        int  fullflag;    /* A stripe is ready to be output */
367
 
        int  stripebytes; /* Number of bytes in a stripe */
368
 
        int  ileave;      /* Interleaving pass: 0=even lines, 1=odd lines */
 
330
        /* Printing offsets */
 
331
        int leftoffset;  /* Start printing offset from left margin */
 
332
        int topoffset;   /* Start printing offset from top margin */
 
333
 
 
334
        /* Resolution settings */
 
335
        int xres;        /* Horizontal dots per inch */
 
336
        int yres;        /* Vertical dots per inch */
 
337
        int xrmul;       /* Horizontal coordinate multiplier */
 
338
        int yrmul;       /* Vertical coordinate multiplier */
 
339
 
 
340
        /* Pagewide status */
 
341
        int curheadpos;  /* Current absolute printhead position */
 
342
        int linetoeject; /* Number of lines for the eject command */
 
343
        int direction;   /* Printing direction for next stripe */
 
344
 
 
345
        /* Alignment data */
 
346
        int bwsep;     /* Nozzle columns separation in B&W/photo cartridge */
 
347
        int colsep;    /* Nozzle columns separation in color cartridge */
 
348
        int vertalign; /* Vertical alignment offset of the two cartridges */
 
349
        int lrhalign;  /* Horizontal alignment between left and right cartridges */
 
350
 
 
351
        /* Data pointers */
 
352
        byte *outdata;    /* Buffer to output data codes for one full stripe */
 
353
        byte *scanbuf;    /* Buffer to contain the rasterized scanlines */
 
354
        FILE *stream;     /* Output stream */
 
355
        lxm_device *dev;  /* Pointer to our device */
 
356
 
 
357
        /* Buffer data */
 
358
        int left, right;  /* Actual left and right margins */
 
359
        int firstline;    /* Head of the circular scanline buffer */
 
360
        int lastblack;    /* Line of last black pass rendered in a color print */
 
361
        int curvline;     /* Current vertical position */
 
362
 
 
363
        /* Stripe related data */
 
364
        byte header[24];  /* Stripe header data */
 
365
        int  fullflag;    /* A stripe is ready to be output */
 
366
        int  stripebytes; /* Number of bytes in a stripe */
 
367
        int  ileave;      /* Interleaving pass: 0=even lines, 1=odd lines */
369
368
 
370
369
} pagedata;
371
370
 
379
378
 * into the printer, we calculate the line width
380
379
 * and then anything between 8.25 and 8.4 inches
381
380
 * is considered to be A4.
382
 
 * This routine is inspired by the omologous 
 
381
 * This routine is inspired by the omologous
383
382
 * routine from the "gdevbj10" driver.
384
383
 */
385
384
static int
386
385
lxm3200_open(gx_device *pdev)
387
386
{
388
 
        float linewidth;
389
 
 
390
 
        static const float a4_margins[4] =
391
 
        {      
392
 
                LXM3200_A4_LEFT_MARGIN, LXM3200_BOTTOM_MARGIN,
393
 
                LXM3200_A4_RIGHT_MARGIN, LXM3200_TOP_MARGIN
394
 
        };
395
 
 
396
 
        static const float letter_margins[4] =
397
 
        {
398
 
                LXM3200_LETTER_LEFT_MARGIN, LXM3200_BOTTOM_MARGIN,
399
 
                LXM3200_LETTER_RIGHT_MARGIN, LXM3200_TOP_MARGIN
400
 
        };
401
 
 
402
 
        linewidth = (float)(pdev->width) / (float)(pdev->x_pixels_per_inch);
403
 
 
404
 
        if(linewidth >= 8.25 && linewidth <= 8.4)
405
 
        {
406
 
                gx_device_set_margins(pdev, a4_margins, true);
407
 
                ((lxm_device *)pdev)->topoffset = LXM3200_A4_TOPOFFSET;
408
 
                ((lxm_device *)pdev)->leftoffset = LXM3200_A4_LEFTOFFSET;
409
 
        }
410
 
        else
411
 
        {
412
 
                gx_device_set_margins(pdev, letter_margins, true);
413
 
                ((lxm_device *)pdev)->topoffset = LXM3200_LETTER_TOPOFFSET;
414
 
                ((lxm_device *)pdev)->leftoffset = LXM3200_LETTER_LEFTOFFSET;
415
 
        }
416
 
        
417
 
        return gdev_prn_open(pdev);
 
387
        float linewidth;
 
388
 
 
389
        static const float a4_margins[4] =
 
390
        {
 
391
                LXM3200_A4_LEFT_MARGIN, LXM3200_BOTTOM_MARGIN,
 
392
                LXM3200_A4_RIGHT_MARGIN, LXM3200_TOP_MARGIN
 
393
        };
 
394
 
 
395
        static const float letter_margins[4] =
 
396
        {
 
397
                LXM3200_LETTER_LEFT_MARGIN, LXM3200_BOTTOM_MARGIN,
 
398
                LXM3200_LETTER_RIGHT_MARGIN, LXM3200_TOP_MARGIN
 
399
        };
 
400
 
 
401
        linewidth = (float)(pdev->width) / (float)(pdev->x_pixels_per_inch);
 
402
 
 
403
        if(linewidth >= 8.25 && linewidth <= 8.4)
 
404
        {
 
405
                gx_device_set_margins(pdev, a4_margins, true);
 
406
                ((lxm_device *)pdev)->topoffset = LXM3200_A4_TOPOFFSET;
 
407
                ((lxm_device *)pdev)->leftoffset = LXM3200_A4_LEFTOFFSET;
 
408
        }
 
409
        else
 
410
        {
 
411
                gx_device_set_margins(pdev, letter_margins, true);
 
412
                ((lxm_device *)pdev)->topoffset = LXM3200_LETTER_TOPOFFSET;
 
413
                ((lxm_device *)pdev)->leftoffset = LXM3200_LETTER_LEFTOFFSET;
 
414
        }
 
415
 
 
416
        return gdev_prn_open(pdev);
418
417
}
419
418
 
420
419
/* Function used by ghostscript to map a RGB
424
423
static gx_color_index
425
424
lxm3200_map_rgb_color(gx_device *dev, const gx_color_value cv[])
426
425
{
427
 
        gx_color_index col;
428
 
        gx_color_value r, g, b;
429
 
        int c, m, y;
430
 
        gx_color_value tmpcv[3];
431
 
        
432
 
        r = cv[0]; g = cv[1]; b = cv[2];
433
 
        /* In case R, G and B values are equal, ghostscript
434
 
         * prescribes that the color value must be turned 
435
 
         * into a gray shade. In our case this means either
436
 
         * black or white
437
 
         */
438
 
        if(r == g && r == b)
439
 
        {
440
 
                if(r > HALFTONE)
441
 
                        return(WHITE);
442
 
                else
443
 
                        return(BLACK);
444
 
        }
445
 
 
446
 
        /* Calculate CMY values from RGB. This is *overly*
447
 
         * simple, but it's enough to print something.
448
 
         */
449
 
        c = FULLTONE - r;
450
 
        m = FULLTONE - g;
451
 
        y = FULLTONE - b;       
452
 
 
453
 
        /* Now encode the calculated color into the internal
454
 
         * format. This means simply to turn on or off the
455
 
         * bits representing each color depending on the value
456
 
         * of the appropriate CMY component.
457
 
         * Note that we are not doing black separation or any
458
 
         * other fancy stuff: this is spartane code just to
459
 
         * make the printer work. 
460
 
         */
461
 
        col = 0;
462
 
        if(y > HALFTONE)col |= YELLOW;
463
 
        
464
 
        switch(((lxm_device *)dev)->rendermode)
465
 
        {
466
 
                case LXM3200_C:
467
 
                        if(c > HALFTONE)col |= CYAN;
468
 
                        if(m > HALFTONE)col |= MAGENTA;
469
 
                        break;
470
 
                                
471
 
                case LXM3200_P:
472
 
                        if(c > TWOTHIRD)
473
 
                                col |= CYAN;
474
 
                        else
475
 
                                if(c > ONETHIRD)col |= LIGHTCYAN;
476
 
 
477
 
                        if(m > TWOTHIRD)
478
 
                                col |= MAGENTA;
479
 
                        else
480
 
                                if(m > ONETHIRD)col |= LIGHTMAGENTA;
481
 
                        break;
482
 
 
483
 
                default:
484
 
                        tmpcv[0] = r; tmpcv[1] = g; tmpcv[2] = b;
485
 
                        col = gdev_prn_map_rgb_color(dev, tmpcv);
486
 
                        break;
487
 
        }
488
 
 
489
 
        return(col);
 
426
        gx_color_index col;
 
427
        gx_color_value r, g, b;
 
428
        int c, m, y;
 
429
        gx_color_value tmpcv[3];
 
430
 
 
431
        r = cv[0]; g = cv[1]; b = cv[2];
 
432
        /* In case R, G and B values are equal, ghostscript
 
433
         * prescribes that the color value must be turned
 
434
         * into a gray shade. In our case this means either
 
435
         * black or white
 
436
         */
 
437
        if(r == g && r == b)
 
438
        {
 
439
                if(r > HALFTONE)
 
440
                        return(WHITE);
 
441
                else
 
442
                        return(BLACK);
 
443
        }
 
444
 
 
445
        /* Calculate CMY values from RGB. This is *overly*
 
446
         * simple, but it's enough to print something.
 
447
         */
 
448
        c = FULLTONE - r;
 
449
        m = FULLTONE - g;
 
450
        y = FULLTONE - b;
 
451
 
 
452
        /* Now encode the calculated color into the internal
 
453
         * format. This means simply to turn on or off the
 
454
         * bits representing each color depending on the value
 
455
         * of the appropriate CMY component.
 
456
         * Note that we are not doing black separation or any
 
457
         * other fancy stuff: this is spartane code just to
 
458
         * make the printer work.
 
459
         */
 
460
        col = 0;
 
461
        if(y > HALFTONE)col |= YELLOW;
 
462
 
 
463
        switch(((lxm_device *)dev)->rendermode)
 
464
        {
 
465
                case LXM3200_C:
 
466
                        if(c > HALFTONE)col |= CYAN;
 
467
                        if(m > HALFTONE)col |= MAGENTA;
 
468
                        break;
 
469
 
 
470
                case LXM3200_P:
 
471
                        if(c > TWOTHIRD)
 
472
                                col |= CYAN;
 
473
                        else
 
474
                                if(c > ONETHIRD)col |= LIGHTCYAN;
 
475
 
 
476
                        if(m > TWOTHIRD)
 
477
                                col |= MAGENTA;
 
478
                        else
 
479
                                if(m > ONETHIRD)col |= LIGHTMAGENTA;
 
480
                        break;
 
481
 
 
482
                default:
 
483
                        tmpcv[0] = r; tmpcv[1] = g; tmpcv[2] = b;
 
484
                        col = gdev_prn_map_rgb_color(dev, tmpcv);
 
485
                        break;
 
486
        }
 
487
 
 
488
        return(col);
490
489
}
491
 
 
 
490
 
492
491
/* Function called by ghostscript to map the
493
492
 * internal representation of a color to a
494
 
 * RGB value. 
 
493
 * RGB value.
495
494
 */
496
495
static int
497
496
lxm3200_map_color_rgb(gx_device *dev, gx_color_index color,
498
 
                                                                                        gx_color_value prgb[3])
 
497
                                                                                        gx_color_value prgb[3])
499
498
{
500
 
        int c, m, y;
501
 
 
502
 
        if(color == WHITE)
503
 
        {
504
 
                prgb[0] = FULLTONE; 
505
 
                prgb[1] = FULLTONE; 
506
 
                prgb[2] = FULLTONE;
507
 
                return(0);
508
 
        }
509
 
        
510
 
        if(color & BLACK)
511
 
        {
512
 
                prgb[0] = 0; 
513
 
                prgb[1] = 0; 
514
 
                prgb[2] = 0;
515
 
                return(0);
516
 
        }
517
 
 
518
 
        /* Calculate back CMY components from the internal
519
 
         * representation of the color
520
 
         */
521
 
        c = 0;
522
 
        m = 0;
523
 
        y = 0;
524
 
        
525
 
        switch(((lxm_device *)dev)->rendermode)
526
 
        {
527
 
                case LXM3200_C:
528
 
                        color &= (CYAN|MAGENTA|YELLOW);
529
 
                        if(color & CYAN)c = 2;
530
 
                        if(color & MAGENTA)m = 2;
531
 
                        if(color & YELLOW)y = 2;
532
 
                        break;
533
 
                        
534
 
                case LXM3200_P:
535
 
                default:
536
 
                        color &= (CYAN|MAGENTA|YELLOW|LIGHTCYAN|LIGHTMAGENTA);
537
 
                        if(color & LIGHTCYAN)c = 1;
538
 
                        if(color & LIGHTMAGENTA)m = 1;
539
 
                        if(color & YELLOW)y = 2;
540
 
                        if(color & CYAN)c = 2;
541
 
                        if(color & MAGENTA)m = 2;
542
 
                        break;
543
 
        }
544
 
 
545
 
        /* And now turn CMY to RGB, in the usual spartane way */
546
 
 
547
 
        prgb[0] = (gx_color_value)((2 - c) * HALFTONE);
548
 
        prgb[1] = (gx_color_value)((2 - m) * HALFTONE);
549
 
        prgb[2] = (gx_color_value)((2 - y) * HALFTONE);
550
 
 
551
 
        return(0);
 
499
        int c, m, y;
 
500
 
 
501
        if(color == WHITE)
 
502
        {
 
503
                prgb[0] = FULLTONE;
 
504
                prgb[1] = FULLTONE;
 
505
                prgb[2] = FULLTONE;
 
506
                return(0);
 
507
        }
 
508
 
 
509
        if(color & BLACK)
 
510
        {
 
511
                prgb[0] = 0;
 
512
                prgb[1] = 0;
 
513
                prgb[2] = 0;
 
514
                return(0);
 
515
        }
 
516
 
 
517
        /* Calculate back CMY components from the internal
 
518
         * representation of the color
 
519
         */
 
520
        c = 0;
 
521
        m = 0;
 
522
        y = 0;
 
523
 
 
524
        switch(((lxm_device *)dev)->rendermode)
 
525
        {
 
526
                case LXM3200_C:
 
527
                        color &= (CYAN|MAGENTA|YELLOW);
 
528
                        if(color & CYAN)c = 2;
 
529
                        if(color & MAGENTA)m = 2;
 
530
                        if(color & YELLOW)y = 2;
 
531
                        break;
 
532
 
 
533
                case LXM3200_P:
 
534
                default:
 
535
                        color &= (CYAN|MAGENTA|YELLOW|LIGHTCYAN|LIGHTMAGENTA);
 
536
                        if(color & LIGHTCYAN)c = 1;
 
537
                        if(color & LIGHTMAGENTA)m = 1;
 
538
                        if(color & YELLOW)y = 2;
 
539
                        if(color & CYAN)c = 2;
 
540
                        if(color & MAGENTA)m = 2;
 
541
                        break;
 
542
        }
 
543
 
 
544
        /* And now turn CMY to RGB, in the usual spartane way */
 
545
 
 
546
        prgb[0] = (gx_color_value)((2 - c) * HALFTONE);
 
547
        prgb[1] = (gx_color_value)((2 - m) * HALFTONE);
 
548
        prgb[2] = (gx_color_value)((2 - y) * HALFTONE);
 
549
 
 
550
        return(0);
552
551
}
553
552
 
554
553
/* Main routine of the driver. This takes care of
555
 
 * all parameters and static data initialization 
 
554
 * all parameters and static data initialization
556
555
 * and calls the proper page printing routines
557
 
 * depending on the selected printing mode. 
 
556
 * depending on the selected printing mode.
558
557
 */
559
 
static int 
 
558
static int
560
559
lxm3200_print_page(gx_device_printer *pdev, FILE *prn_stream)
561
560
{
562
 
        /* Store data passed by ghostscript to the driver */
563
 
        gendata.dev = (lxm_device *)pdev;
564
 
        gendata.stream = prn_stream;
565
 
        gendata.rendermode = (gendata.dev)->rendermode;
566
 
                
567
 
        /* Snap resolution on one of the three supported setting
568
 
         * (300, 600, 1200 dpi) depending on the input resoution value.
569
 
         * Horizontal and vertical resolution are treated independently. 
 
561
        /* Store data passed by ghostscript to the driver */
 
562
        gendata.dev = (lxm_device *)pdev;
 
563
        gendata.stream = prn_stream;
 
564
        gendata.rendermode = (gendata.dev)->rendermode;
 
565
 
 
566
        /* Snap resolution on one of the three supported setting
 
567
         * (300, 600, 1200 dpi) depending on the input resoution value.
 
568
         * Horizontal and vertical resolution are treated independently.
570
569
   */
571
 
        gendata.xres = 600;
572
 
        if((gendata.dev)->x_pixels_per_inch < 450)gendata.xres = 300;
573
 
        if((gendata.dev)->x_pixels_per_inch > 900)gendata.xres = 1200;
574
 
        gendata.xrmul = 1200 / gendata.xres;
575
 
 
576
 
        gendata.yres = 600;
577
 
        if((gendata.dev)->y_pixels_per_inch < 450)gendata.yres = 300;
578
 
        if((gendata.dev)->y_pixels_per_inch > 900)gendata.yres = 1200;
579
 
        gendata.yrmul = 1200 / gendata.yres;
580
 
 
581
 
        /* Cache horizontal and vertical starting offsets */
582
 
        gendata.topoffset = (gendata.dev)->topoffset;
583
 
        gendata.leftoffset = (gendata.dev)->leftoffset;
584
 
 
585
 
        /* Build lookup table for pen offset, adjusting for
586
 
         * vertical resolution setting 
587
 
         */
588
 
        penofs[0] = (PEN0OFS * 2) / gendata.yrmul;
589
 
        penofs[1] = (PEN1OFS * 2) / gendata.yrmul;
590
 
        penofs[2] = (PEN2OFS * 2) / gendata.yrmul;
591
 
        
592
 
        /* Build lookup table for vertical heads alignment,
593
 
         * adjusting for vertical resolution setting
594
 
         */
595
 
        valign[COLORVALIGN] = (COLORVALIGN_V * 2) / gendata.yrmul;
596
 
        valign[BLACKVALIGN] = (BLACKVALIGN_V * 2) / gendata.yrmul;
597
 
        valign[PHOTOVALIGN] = (PHOTOVALIGN_V * 2) / gendata.yrmul;
598
 
      
599
 
        /* Build lookup tables for initial horizontal offsets,
600
 
         * adjusting for horizontal resolution setting
601
 
         */
602
 
         /* choose whether to use lxm3200 or Z12 settings */
 
570
        gendata.xres = 600;
 
571
        if((gendata.dev)->x_pixels_per_inch < 450)gendata.xres = 300;
 
572
        if((gendata.dev)->x_pixels_per_inch > 900)gendata.xres = 1200;
 
573
        gendata.xrmul = 1200 / gendata.xres;
 
574
 
 
575
        gendata.yres = 600;
 
576
        if((gendata.dev)->y_pixels_per_inch < 450)gendata.yres = 300;
 
577
        if((gendata.dev)->y_pixels_per_inch > 900)gendata.yres = 1200;
 
578
        gendata.yrmul = 1200 / gendata.yres;
 
579
 
 
580
        /* Cache horizontal and vertical starting offsets */
 
581
        gendata.topoffset = (gendata.dev)->topoffset;
 
582
        gendata.leftoffset = (gendata.dev)->leftoffset;
 
583
 
 
584
        /* Build lookup table for pen offset, adjusting for
 
585
         * vertical resolution setting
 
586
         */
 
587
        penofs[0] = (PEN0OFS * 2) / gendata.yrmul;
 
588
        penofs[1] = (PEN1OFS * 2) / gendata.yrmul;
 
589
        penofs[2] = (PEN2OFS * 2) / gendata.yrmul;
 
590
 
 
591
        /* Build lookup table for vertical heads alignment,
 
592
         * adjusting for vertical resolution setting
 
593
         */
 
594
        valign[COLORVALIGN] = (COLORVALIGN_V * 2) / gendata.yrmul;
 
595
        valign[BLACKVALIGN] = (BLACKVALIGN_V * 2) / gendata.yrmul;
 
596
        valign[PHOTOVALIGN] = (PHOTOVALIGN_V * 2) / gendata.yrmul;
 
597
 
 
598
        /* Build lookup tables for initial horizontal offsets,
 
599
         * adjusting for horizontal resolution setting
 
600
         */
 
601
         /* choose whether to use lxm3200 or Z12 settings */
603
602
      gendata.modelprint=(gendata.dev)->model; /* which model? */
604
603
      gendata.z31margin=(gendata.dev)->z31m; /*which additional margin for z31*/
605
604
      switch(gendata.modelprint){
606
605
      case 1:  /* we use the Lexmark Z12 */
607
606
          hoffset[LEFT][LEFT] = LHSTART_z12;
608
 
          hoffset[RIGHT][LEFT] = RHSTART_z12 + gendata.lrhalign;
609
 
          break;
 
607
          hoffset[RIGHT][LEFT] = RHSTART_z12 + gendata.lrhalign;
 
608
          break;
610
609
      default: /* default (if one uses the Lexmark 3200 or the Lexmark Z31) */
611
610
          hoffset[LEFT][LEFT] = LHSTART;
612
611
          hoffset[RIGHT][LEFT] = RHSTART + gendata.lrhalign;
613
612
          break;
614
613
      }
615
 
      hoffset[LEFT][RIGHT] = hoffset[LEFT][LEFT] - LRPASSHOFS; 
 
614
      hoffset[LEFT][RIGHT] = hoffset[LEFT][LEFT] - LRPASSHOFS;
616
615
      hoffset[RIGHT][RIGHT] = hoffset[RIGHT][LEFT] - LRPASSHOFS;
617
616
 
618
 
        /* Initialization of general parameters */
619
 
        gendata.outdata = NULL;
620
 
        gendata.scanbuf = NULL;
621
 
        gendata.curheadpos = 0;
622
 
        gendata.left = 0;
623
 
        gendata.right = 0;
624
 
        gendata.lastblack = 0;
625
 
        gendata.curvline = 0;
626
 
        gendata.firstline = 0;
627
 
        gendata.fullflag = FALSE;
628
 
        gendata.direction = LEFT;
629
 
        gendata.ileave = 0;
630
 
 
631
 
        gendata.bidirprint = (gendata.dev)->bidir;
632
 
        gendata.numpasses = (gendata.dev)->numpass;
633
 
 
634
 
 
635
 
        /* Set some parameters that depend on resolution and 
636
 
         * printing mode. We calculate all at 600dpi (the native
637
 
         * resolution) and then correct later for different
638
 
         * resolution settings.
639
 
         */
640
 
        switch(gendata.rendermode)
641
 
        {
642
 
                /* In monochrome mode we try to use all 208 nozzles of
643
 
                 * the black cartridge to speed up printing. But if we
644
 
                 * are printing at 1200 dpi horizontal, only 192 nozzles
645
 
                 * are available anyway (it seems an hardware limitation).
646
 
                 * We print a full buffer at every pass, so the number of
647
 
                 * lines in the buffer is the same as the number of nozzles 
648
 
                 * of the head. 
649
 
                 */
650
 
                case LXM3200_M:
651
 
                        gendata.numblines = 208;
652
 
                        gendata.numlines = 208;
653
 
                        gendata.select = 0x10;
654
 
                        if(gendata.xres == 1200)
655
 
                        {
656
 
                                gendata.numblines = 192;
657
 
                                gendata.numlines = 192;
658
 
                                gendata.select = 0x00;
659
 
                        }
660
 
                        break;
661
 
 
662
 
                /* In color or photo mode we must use 192 nozzles only in
663
 
                 * the black cartridge, to cope with the color and photo
664
 
                 * cartridges (which have 3 color pen of 64 nozzles each,
665
 
                 * for a total of 192 nozzles). But the color pens are 
666
 
                 * vertically spaced and misaligned with respect to the
667
 
                 * black pen. To solve this problem, we need a buffer which
668
 
                 * is larger than 192 lines and then we print only the 
669
 
                 * proper "windows" from it. We choose to set the buffer
670
 
                 * height to 256, which is the smallest power of two large
671
 
                 * enough to hold all the needed data. We use a power of
672
 
                 * two for speed, since in this way the modulo operation
673
 
                 * in the inner loops (needed to take care of buffer rolling) 
674
 
                 * becomes a simple and much faster bitwise AND.
675
 
                 */
676
 
                case LXM3200_P:
677
 
                case LXM3200_C:
678
 
                        gendata.numblines = 256;
679
 
                        gendata.numlines = 192;
680
 
                        gendata.select = 0x00;
681
 
                        break;
682
 
        }
683
 
 
684
 
        /* Correct the number of lines of the buffer to take care
685
 
         * of different vertical resolution modes. Since the buffer
686
 
         * does cover a constant vertical spacing, we must double the
687
 
         * number of lines at 1200dpi and half it at 300dpi, to take
688
 
         * into account the different thickness of the lines at the
689
 
         * three different vertical resolutions.
690
 
         */
691
 
        gendata.numblines = (gendata.numblines * 2) / gendata.yrmul;
692
 
 
693
 
        /* Now correct the "select" field to adjust the horizontal
694
 
         * motor speed depending on position. Meanwhile, if we are
695
 
         * at 1200 dpi, double the number of horizontal passes
696
 
         * because each stripe at 1200 dpi horizontal must be printed
697
 
         * in two passes.
698
 
         */
699
 
        switch(gendata.xres)
700
 
        {
701
 
                case 300:
702
 
                        gendata.select |= 0x60;
703
 
                        break;
704
 
 
705
 
                case 1200:
706
 
                        gendata.select |= 0x40;
707
 
                        gendata.numpasses *= 2;
708
 
                        break;
709
 
        }
710
 
 
711
 
        /* Now store some useful info taken from the ghostscript
712
 
         * device structure to speed up access.
713
 
         */
714
 
        gendata.numcols = (gendata.dev)->width;
715
 
        gendata.numvlines = (gendata.dev)->height;
716
 
        gendata.lrhalign = (gendata.dev)->algnA;
717
 
        gendata.vertalign = (gendata.dev)->algnB;
718
 
        gendata.bwsep = (gendata.dev)->algnC;
719
 
        gendata.colsep = (gendata.dev)->algnD;
720
 
        gendata.goffset = (max(gendata.bwsep, gendata.colsep) * 2) / gendata.xrmul;
721
 
        gendata.numbytes = gendata.numcols + (2 * gendata.goffset);
722
 
        gendata.numrbytes = gdev_mem_bytes_per_scan_line(gendata.dev);
723
 
 
724
 
        /* Calculate number of lines in the page and initialize the
725
 
         * counter of the lines to eject. At the end of the printing,
726
 
         * to eject the paper sheet we must send to the printer a
727
 
         * command to move the paper forward. The amount to move is
728
 
         * the length of paper which is still inside the printer plus 
729
 
         * two inches (the number is expressed in 1200ths of an inch, 
730
 
         * so "plus two inches" means "add 2400").
731
 
         */
732
 
        gendata.linetoeject = gendata.numvlines * gendata.yrmul;
733
 
        gendata.linetoeject += 2400;
734
 
 
735
 
        /* Allocate memory for the buffers and
736
 
         * verify that the allocation was done properly.
737
 
         */
738
 
        gendata.scanbuf = (byte *)gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), gendata.numbytes, gendata.numblines, 
739
 
                                                                                                                                                        "lxm3200_print_page(scanbuf)");
740
 
 
741
 
        gendata.outdata = (byte *)gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), gendata.numbytes, 30, 
742
 
                                                                                                                                                        "lxm3200_print_page(outdata)");
743
 
 
744
 
        if(gendata.scanbuf == NULL || 
745
 
                 gendata.outdata == NULL)
746
 
        {
747
 
                freeresources(pdev);
748
 
                return_error(gs_error_VMerror);
749
 
        }
750
 
 
751
 
        /* Send initialization sequence to the printer */
752
 
        if(gendata.modelprint==1) fwrite(z12_init_sequence, sizeof(z12_init_sequence), 1, prn_stream);
753
 
        else fwrite(init_sequence, sizeof(init_sequence), 1, prn_stream);
754
 
 
755
 
        /* Choose the right page printing routine 
756
 
         * depending on the printing mode.
757
 
         */  
758
 
        switch(gendata.rendermode)
759
 
        {
760
 
                case LXM3200_P:
761
 
                        print_photo_page();
762
 
                        break;
763
 
 
764
 
                case LXM3200_C:
765
 
                        print_color_page();
766
 
                        break;
767
 
 
768
 
                case LXM3200_M:
769
 
                default:
770
 
                        print_mono_page();
771
 
                        break;
772
 
        }
773
 
 
774
 
        /* Output the end-of-page epilogue */
775
 
        outputepilogue();
776
 
 
777
 
        /* Free the allocated resources */
778
 
        freeresources(pdev);
779
 
 
780
 
        /* Done. Bye bye, see you on next page. */
781
 
        return(0);
 
617
        /* Initialization of general parameters */
 
618
        gendata.outdata = NULL;
 
619
        gendata.scanbuf = NULL;
 
620
        gendata.curheadpos = 0;
 
621
        gendata.left = 0;
 
622
        gendata.right = 0;
 
623
        gendata.lastblack = 0;
 
624
        gendata.curvline = 0;
 
625
        gendata.firstline = 0;
 
626
        gendata.fullflag = FALSE;
 
627
        gendata.direction = LEFT;
 
628
        gendata.ileave = 0;
 
629
 
 
630
        gendata.bidirprint = (gendata.dev)->bidir;
 
631
        gendata.numpasses = (gendata.dev)->numpass;
 
632
 
 
633
        /* Set some parameters that depend on resolution and
 
634
         * printing mode. We calculate all at 600dpi (the native
 
635
         * resolution) and then correct later for different
 
636
         * resolution settings.
 
637
         */
 
638
        switch(gendata.rendermode)
 
639
        {
 
640
                /* In monochrome mode we try to use all 208 nozzles of
 
641
                 * the black cartridge to speed up printing. But if we
 
642
                 * are printing at 1200 dpi horizontal, only 192 nozzles
 
643
                 * are available anyway (it seems an hardware limitation).
 
644
                 * We print a full buffer at every pass, so the number of
 
645
                 * lines in the buffer is the same as the number of nozzles
 
646
                 * of the head.
 
647
                 */
 
648
                case LXM3200_M:
 
649
                        gendata.numblines = 208;
 
650
                        gendata.numlines = 208;
 
651
                        gendata.select = 0x10;
 
652
                        if(gendata.xres == 1200)
 
653
                        {
 
654
                                gendata.numblines = 192;
 
655
                                gendata.numlines = 192;
 
656
                                gendata.select = 0x00;
 
657
                        }
 
658
                        break;
 
659
 
 
660
                /* In color or photo mode we must use 192 nozzles only in
 
661
                 * the black cartridge, to cope with the color and photo
 
662
                 * cartridges (which have 3 color pen of 64 nozzles each,
 
663
                 * for a total of 192 nozzles). But the color pens are
 
664
                 * vertically spaced and misaligned with respect to the
 
665
                 * black pen. To solve this problem, we need a buffer which
 
666
                 * is larger than 192 lines and then we print only the
 
667
                 * proper "windows" from it. We choose to set the buffer
 
668
                 * height to 256, which is the smallest power of two large
 
669
                 * enough to hold all the needed data. We use a power of
 
670
                 * two for speed, since in this way the modulo operation
 
671
                 * in the inner loops (needed to take care of buffer rolling)
 
672
                 * becomes a simple and much faster bitwise AND.
 
673
                 */
 
674
                case LXM3200_P:
 
675
                case LXM3200_C:
 
676
                        gendata.numblines = 256;
 
677
                        gendata.numlines = 192;
 
678
                        gendata.select = 0x00;
 
679
                        break;
 
680
        }
 
681
 
 
682
        /* Correct the number of lines of the buffer to take care
 
683
         * of different vertical resolution modes. Since the buffer
 
684
         * does cover a constant vertical spacing, we must double the
 
685
         * number of lines at 1200dpi and half it at 300dpi, to take
 
686
         * into account the different thickness of the lines at the
 
687
         * three different vertical resolutions.
 
688
         */
 
689
        gendata.numblines = (gendata.numblines * 2) / gendata.yrmul;
 
690
 
 
691
        /* Now correct the "select" field to adjust the horizontal
 
692
         * motor speed depending on position. Meanwhile, if we are
 
693
         * at 1200 dpi, double the number of horizontal passes
 
694
         * because each stripe at 1200 dpi horizontal must be printed
 
695
         * in two passes.
 
696
         */
 
697
        switch(gendata.xres)
 
698
        {
 
699
                case 300:
 
700
                        gendata.select |= 0x60;
 
701
                        break;
 
702
 
 
703
                case 1200:
 
704
                        gendata.select |= 0x40;
 
705
                        gendata.numpasses *= 2;
 
706
                        break;
 
707
        }
 
708
 
 
709
        /* Now store some useful info taken from the ghostscript
 
710
         * device structure to speed up access.
 
711
         */
 
712
        gendata.numcols = (gendata.dev)->width;
 
713
        gendata.numvlines = (gendata.dev)->height;
 
714
        gendata.lrhalign = (gendata.dev)->algnA;
 
715
        gendata.vertalign = (gendata.dev)->algnB;
 
716
        gendata.bwsep = (gendata.dev)->algnC;
 
717
        gendata.colsep = (gendata.dev)->algnD;
 
718
        gendata.goffset = (max(gendata.bwsep, gendata.colsep) * 2) / gendata.xrmul;
 
719
        gendata.numbytes = gendata.numcols + (2 * gendata.goffset);
 
720
        gendata.numrbytes = gdev_mem_bytes_per_scan_line(gendata.dev);
 
721
 
 
722
        /* Calculate number of lines in the page and initialize the
 
723
         * counter of the lines to eject. At the end of the printing,
 
724
         * to eject the paper sheet we must send to the printer a
 
725
         * command to move the paper forward. The amount to move is
 
726
         * the length of paper which is still inside the printer plus
 
727
         * two inches (the number is expressed in 1200ths of an inch,
 
728
         * so "plus two inches" means "add 2400").
 
729
         */
 
730
        gendata.linetoeject = gendata.numvlines * gendata.yrmul;
 
731
        gendata.linetoeject += 2400;
 
732
 
 
733
        /* Allocate memory for the buffers and
 
734
         * verify that the allocation was done properly.
 
735
         */
 
736
        gendata.scanbuf = (byte *)gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), gendata.numbytes, gendata.numblines,
 
737
                                                                                                                                                        "lxm3200_print_page(scanbuf)");
 
738
 
 
739
        gendata.outdata = (byte *)gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), gendata.numbytes, 30,
 
740
                                                                                                                                                        "lxm3200_print_page(outdata)");
 
741
 
 
742
        if(gendata.scanbuf == NULL ||
 
743
                 gendata.outdata == NULL)
 
744
        {
 
745
                freeresources(pdev);
 
746
                return_error(gs_error_VMerror);
 
747
        }
 
748
 
 
749
        /* Send initialization sequence to the printer */
 
750
        if(gendata.modelprint==1) fwrite(z12_init_sequence, sizeof(z12_init_sequence), 1, prn_stream);
 
751
        else fwrite(init_sequence, sizeof(init_sequence), 1, prn_stream);
 
752
 
 
753
        /* Choose the right page printing routine
 
754
         * depending on the printing mode.
 
755
         */
 
756
        switch(gendata.rendermode)
 
757
        {
 
758
                case LXM3200_P:
 
759
                        print_photo_page();
 
760
                        break;
 
761
 
 
762
                case LXM3200_C:
 
763
                        print_color_page();
 
764
                        break;
 
765
 
 
766
                case LXM3200_M:
 
767
                default:
 
768
                        print_mono_page();
 
769
                        break;
 
770
        }
 
771
 
 
772
        /* Output the end-of-page epilogue */
 
773
        outputepilogue();
 
774
 
 
775
        /* Free the allocated resources */
 
776
        freeresources(pdev);
 
777
 
 
778
        /* Done. Bye bye, see you on next page. */
 
779
        return(0);
782
780
}
783
781
 
784
782
/* Function that Ghostscript calls to ask the driver
785
 
 * the value of its parameters. This function is based 
 
783
 * the value of its parameters. This function is based
786
784
 * on the equivalent from the HP850 driver (gdevcd8.c)
787
785
 * by Uli Wortmann.
788
786
 * I won't comment it because I haven't even tried
792
790
lxm3200_get_params(gx_device *pdev, gs_param_list *plist)
793
791
{
794
792
  int code;
795
 
 
 
793
 
796
794
  code = gdev_prn_get_params(pdev, plist);
797
795
 
798
796
  if(code < 0)return(code);
799
797
 
800
 
        code = param_write_int(plist, "algnA", &((lxm_device *)pdev)->algnA);
801
 
        if(code < 0)return(code);
802
 
 
803
 
        code = param_write_int(plist, "algnB", &((lxm_device *)pdev)->algnB);
804
 
        if(code < 0)return(code);
805
 
 
806
 
        code = param_write_int(plist, "algnC", &((lxm_device *)pdev)->algnC);
807
 
        if(code < 0)return(code);
808
 
 
809
 
        code = param_write_int(plist, "algnD", &((lxm_device *)pdev)->algnD);
810
 
        if(code < 0)return(code);
811
 
 
812
 
        code = param_write_int(plist, "bidir", &((lxm_device *)pdev)->bidir);
813
 
        if(code < 0)return(code);
814
 
 
815
 
        code = param_write_int(plist, "numpass", &((lxm_device *)pdev)->numpass);
816
 
        if(code < 0)return(code);
817
 
 
818
 
        code = param_write_int(plist, "mode", &((lxm_device *)pdev)->rendermode);
 
798
        code = param_write_int(plist, "algnA", &((lxm_device *)pdev)->algnA);
 
799
        if(code < 0)return(code);
 
800
 
 
801
        code = param_write_int(plist, "algnB", &((lxm_device *)pdev)->algnB);
 
802
        if(code < 0)return(code);
 
803
 
 
804
        code = param_write_int(plist, "algnC", &((lxm_device *)pdev)->algnC);
 
805
        if(code < 0)return(code);
 
806
 
 
807
        code = param_write_int(plist, "algnD", &((lxm_device *)pdev)->algnD);
 
808
        if(code < 0)return(code);
 
809
 
 
810
        code = param_write_int(plist, "bidir", &((lxm_device *)pdev)->bidir);
 
811
        if(code < 0)return(code);
 
812
 
 
813
        code = param_write_int(plist, "numpass", &((lxm_device *)pdev)->numpass);
 
814
        if(code < 0)return(code);
 
815
 
 
816
        code = param_write_int(plist, "mode", &((lxm_device *)pdev)->rendermode);
819
817
        if(code < 0)return(code);
820
818
 
821
819
        code = param_write_int(plist, "model", &((lxm_device *)pdev)->model);
822
820
        if(code < 0)return(code);
823
821
 
824
 
        code = param_write_int(plist, "z31m", &((lxm_device *)pdev)->z31m);
 
822
        code = param_write_int(plist, "z31m", &((lxm_device *)pdev)->z31m);
825
823
 
826
824
  return code;
827
825
}
828
826
 
829
827
/* Function that Ghostscript calls to let the driver
830
 
 * set the value of its parameters. This function is 
831
 
 * based on the equivalent from the HP850 driver 
 
828
 * set the value of its parameters. This function is
 
829
 * based on the equivalent from the HP850 driver
832
830
 * (gdevcd8.c) by Uli Wortmann.
833
831
 * I won't comment it because I haven't even tried
834
832
 * to understand this code... :)
835
833
 */
836
834
static int
837
835
lxm3200_put_params(gx_device *pdev, gs_param_list *plist)
838
 
{       
 
836
{
839
837
  int algnA = ((lxm_device *)pdev)->algnA;
840
838
  int algnB = ((lxm_device *)pdev)->algnB;
841
839
  int algnC = ((lxm_device *)pdev)->algnC;
848
846
  int z31m = ((lxm_device *)pdev)->z31m; /* additional margin for the z31 */
849
847
 
850
848
  code = param_read_int(plist, "algnA", &algnA);
851
 
        if(code < 0)return(code);
852
 
        if(algnA < 0 || algnA > 30)
853
 
                param_signal_error(plist, "algnA", gs_error_rangecheck);
 
849
        if(code < 0)return(code);
 
850
        if(algnA < 0 || algnA > 30)
 
851
                param_signal_error(plist, "algnA", gs_error_rangecheck);
854
852
 
855
853
  code = param_read_int(plist, "algnB", &algnB);
856
 
        if(code < 0)return(code);
857
 
        if(algnB < 0 || algnB > 15)
858
 
                param_signal_error(plist, "algnB", gs_error_rangecheck);
 
854
        if(code < 0)return(code);
 
855
        if(algnB < 0 || algnB > 15)
 
856
                param_signal_error(plist, "algnB", gs_error_rangecheck);
859
857
 
860
858
  code = param_read_int(plist, "algnC", &algnC);
861
 
        if(code < 0)return(code);
862
 
        if(algnC < 0 || algnC > 30)
863
 
                param_signal_error(plist, "algnC", gs_error_rangecheck);
 
859
        if(code < 0)return(code);
 
860
        if(algnC < 0 || algnC > 30)
 
861
                param_signal_error(plist, "algnC", gs_error_rangecheck);
864
862
 
865
863
  code = param_read_int(plist, "algnD", &algnD);
866
 
        if(code < 0)return(code);
867
 
        if(algnD < 0 || algnD > 30)
868
 
                param_signal_error(plist, "algnD", gs_error_rangecheck);
 
864
        if(code < 0)return(code);
 
865
        if(algnD < 0 || algnD > 30)
 
866
                param_signal_error(plist, "algnD", gs_error_rangecheck);
869
867
 
870
868
  code = param_read_int(plist, "bidir", &bidir);
871
 
        if(code < 0)return(code);
872
 
        if(bidir != 0 && bidir != 1)
873
 
                param_signal_error(plist, "bidir", gs_error_rangecheck);
 
869
        if(code < 0)return(code);
 
870
        if(bidir != 0 && bidir != 1)
 
871
                param_signal_error(plist, "bidir", gs_error_rangecheck);
874
872
 
875
873
  code = param_read_int(plist, "numpass", &numpass);
876
 
        if(code < 0)return(code);
877
 
        if(numpass < 1 || numpass > 16)
878
 
                param_signal_error(plist, "numpass", gs_error_rangecheck);
 
874
        if(code < 0)return(code);
 
875
        if(numpass < 1 || numpass > 16)
 
876
                param_signal_error(plist, "numpass", gs_error_rangecheck);
879
877
 
880
878
  code = param_read_int(plist, "mode", &mode);
881
 
        if(code < 0)return(code);
882
 
        if(mode != LXM3200_M && mode != LXM3200_C && mode != LXM3200_P)
883
 
                param_signal_error(plist, "mode", gs_error_rangecheck);
 
879
        if(code < 0)return(code);
 
880
        if(mode != LXM3200_M && mode != LXM3200_C && mode != LXM3200_P)
 
881
                param_signal_error(plist, "mode", gs_error_rangecheck);
884
882
 
885
883
   code = param_read_int(plist, "model", &model); /* asking for the model of printer: lxm3200 , Z12, Z31 */
886
 
        if(code < 0)return(code);
887
 
        if(model < 0 || model > 2 )
888
 
                param_signal_error(plist, "model", gs_error_rangecheck);
 
884
        if(code < 0)return(code);
 
885
        if(model < 0 || model > 2 )
 
886
                param_signal_error(plist, "model", gs_error_rangecheck);
889
887
 
890
888
   code = param_read_int(plist, "z31m", &z31m); /* What additional margin for the Z31 */
891
 
        if(code < 0)return(code);
 
889
        if(code < 0)return(code);
892
890
 
893
 
   code = gdev_prn_put_params(pdev, plist);    
 
891
   code = gdev_prn_put_params(pdev, plist);
894
892
        if(code < 0)return code;
895
893
 
896
894
  ((lxm_device *)pdev)->algnA = algnA;
903
901
  ((lxm_device *)pdev)->model = model; /* Model selection: lxm3200, Z12, Z31. */
904
902
  ((lxm_device *)pdev)->z31m = z31m;  /* Additional margin for the Z31 */
905
903
 
906
 
        /* Depending on the selected rendering mode, change the
907
 
         * driver's parameters that ghostscript needs for the
908
 
         * dithering. We need to do it here because the "get_params"
909
 
         * and "put_params" are the only routines in the driver that
910
 
         * ghostscript calls before using the dithering parameters.
911
 
         */
912
 
        switch(mode)
913
 
        {
914
 
                case LXM3200_M:
915
 
                        pdev->color_info.num_components = 1;
916
 
                        pdev->color_info.max_gray = 1;
917
 
                        pdev->color_info.max_color = 0;
918
 
                        pdev->color_info.dither_grays = 2;
919
 
                        pdev->color_info.dither_colors = 0;
920
 
                        break;
921
 
 
922
 
                case LXM3200_C:
923
 
                        pdev->color_info.num_components = 3;
924
 
                        pdev->color_info.max_gray = 1;
925
 
                        pdev->color_info.max_color = 1;
926
 
                        pdev->color_info.dither_grays = 2;
927
 
                        pdev->color_info.dither_colors = 2;
928
 
                        break;
929
 
 
930
 
                case LXM3200_P:
931
 
                        pdev->color_info.num_components = 3;
932
 
                        pdev->color_info.max_gray = 1;
933
 
                        pdev->color_info.max_color = 2;
934
 
                        pdev->color_info.dither_grays = 2;
935
 
                        pdev->color_info.dither_colors = 3;
936
 
                        break;
937
 
        }
 
904
        /* Depending on the selected rendering mode, change the
 
905
         * driver's parameters that ghostscript needs for the
 
906
         * dithering. We need to do it here because the "get_params"
 
907
         * and "put_params" are the only routines in the driver that
 
908
         * ghostscript calls before using the dithering parameters.
 
909
         */
 
910
        switch(mode)
 
911
        {
 
912
                case LXM3200_M:
 
913
                        pdev->color_info.num_components = 1;
 
914
                        pdev->color_info.max_gray = 1;
 
915
                        pdev->color_info.max_color = 0;
 
916
                        pdev->color_info.dither_grays = 2;
 
917
                        pdev->color_info.dither_colors = 0;
 
918
                        break;
 
919
 
 
920
                case LXM3200_C:
 
921
                        pdev->color_info.num_components = 3;
 
922
                        pdev->color_info.max_gray = 1;
 
923
                        pdev->color_info.max_color = 1;
 
924
                        pdev->color_info.dither_grays = 2;
 
925
                        pdev->color_info.dither_colors = 2;
 
926
                        break;
 
927
 
 
928
                case LXM3200_P:
 
929
                        pdev->color_info.num_components = 3;
 
930
                        pdev->color_info.max_gray = 1;
 
931
                        pdev->color_info.max_color = 2;
 
932
                        pdev->color_info.dither_grays = 2;
 
933
                        pdev->color_info.dither_colors = 3;
 
934
                        break;
 
935
        }
938
936
 
939
937
  return 0;
940
938
}
941
939
 
942
 
 
943
940
/* --------- Internal routines --------- */
944
941
 
945
942
/* Free the resources allocated by the driver */
946
943
static void
947
944
freeresources(gx_device *pdev)
948
945
{
949
 
        if(gendata.scanbuf)
950
 
                gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char *)gendata.scanbuf, gendata.numbytes, gendata.numblines,
951
 
                                                "lxm3200:freeresources(scanbuf)");
 
946
        if(gendata.scanbuf)
 
947
                gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char *)gendata.scanbuf, gendata.numbytes, gendata.numblines,
 
948
                                                "lxm3200:freeresources(scanbuf)");
952
949
 
953
 
        if(gendata.outdata)
954
 
                gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char *)gendata.outdata, gendata.numbytes, 30, 
955
 
                                                "lxm3200:freeresources(outdata)");
 
950
        if(gendata.outdata)
 
951
                gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char *)gendata.outdata, gendata.numbytes, 30,
 
952
                                                "lxm3200:freeresources(outdata)");
956
953
}
957
954
 
958
955
/* Calculate the checksum of an escape sequence.
959
 
 * It is defined as the sum modulo 256 of the 
 
956
 * It is defined as the sum modulo 256 of the
960
957
 * six bytes following the escape character.
961
958
 *
962
959
 * data: pointer to the first of the 8 characters
963
960
 *       of an escape sequence.
964
961
 */
965
 
static byte 
 
962
static byte
966
963
calccheck8(byte *data)
967
964
{
968
 
        int ck, i;
969
 
        
970
 
        ck = 0;
971
 
        for(i=1; i<7; i++)ck += data[i];
972
 
        
973
 
        return(ck);
 
965
        int ck, i;
 
966
 
 
967
        ck = 0;
 
968
        for(i=1; i<7; i++)ck += data[i];
 
969
 
 
970
        return(ck);
974
971
}
975
972
 
976
973
/* Output the page epilogue. This procedure outputs
977
974
 * the escape sequence needed to eject the page and
978
975
 * take the printheads to the "park" position.
979
976
 */
980
 
static void 
 
977
static void
981
978
outputepilogue(void)
982
979
{
983
 
        byte trailer[24];
984
 
        int pos;
985
 
        
986
 
        /* Page eject sequence */
987
 
        trailer[0] = 0x1b;
988
 
        trailer[1] = 0x22;
989
 
        trailer[2] = 0x80;
990
 
        trailer[3] = gendata.linetoeject >> 8;
991
 
        trailer[4] = gendata.linetoeject & 0xff;
992
 
        trailer[5] = 0x00;
993
 
        trailer[6] = 0x00;
994
 
        trailer[7] = calccheck8(trailer);
995
 
 
996
 
        /* Calculate the value we need to take the head back
997
 
         * to the park position. This is the current head position
998
 
         * if we printed the last stripe left-to-right, and the
999
 
         * current head position minus 168 (0xa8) if we printed the
1000
 
         * last stripe right-to-left.
1001
 
         */
1002
 
        pos = gendata.curheadpos;
1003
 
        if(gendata.bidirprint && gendata.direction == LEFT)pos -= 0xa8;
1004
 
        if(pos < 0)pos = 0;
1005
 
 
1006
 
        /* Horizontal back sequence */
1007
 
        trailer[8] = 0x1b;
1008
 
        trailer[9] = 0x31;
1009
 
        trailer[10] = 0x10;
1010
 
        trailer[11] = pos >> 8;
1011
 
        trailer[12] = pos & 0xff;
1012
 
        trailer[13] = 0x00;
1013
 
        trailer[14] = 0x00;
1014
 
        trailer[15] = calccheck8(trailer+8);
1015
 
        
1016
 
        /* Reset sequence */
1017
 
        trailer[16] = 0x1b;
1018
 
        trailer[17] = 0x33;
1019
 
        trailer[18] = 0x00;
1020
 
        trailer[19] = 0x00;
1021
 
        trailer[20] = 0x00;
1022
 
        trailer[21] = 0x00;
1023
 
        trailer[22] = 0x00;
1024
 
        trailer[23] = 0x33;
1025
 
        
1026
 
        fwrite(trailer, 8, 3, gendata.stream);
 
980
        byte trailer[24];
 
981
        int pos;
 
982
 
 
983
        /* Page eject sequence */
 
984
        trailer[0] = 0x1b;
 
985
        trailer[1] = 0x22;
 
986
        trailer[2] = 0x80;
 
987
        trailer[3] = gendata.linetoeject >> 8;
 
988
        trailer[4] = gendata.linetoeject & 0xff;
 
989
        trailer[5] = 0x00;
 
990
        trailer[6] = 0x00;
 
991
        trailer[7] = calccheck8(trailer);
 
992
 
 
993
        /* Calculate the value we need to take the head back
 
994
         * to the park position. This is the current head position
 
995
         * if we printed the last stripe left-to-right, and the
 
996
         * current head position minus 168 (0xa8) if we printed the
 
997
         * last stripe right-to-left.
 
998
         */
 
999
        pos = gendata.curheadpos;
 
1000
        if(gendata.bidirprint && gendata.direction == LEFT)pos -= 0xa8;
 
1001
        if(pos < 0)pos = 0;
 
1002
 
 
1003
        /* Horizontal back sequence */
 
1004
        trailer[8] = 0x1b;
 
1005
        trailer[9] = 0x31;
 
1006
        trailer[10] = 0x10;
 
1007
        trailer[11] = pos >> 8;
 
1008
        trailer[12] = pos & 0xff;
 
1009
        trailer[13] = 0x00;
 
1010
        trailer[14] = 0x00;
 
1011
        trailer[15] = calccheck8(trailer+8);
 
1012
 
 
1013
        /* Reset sequence */
 
1014
        trailer[16] = 0x1b;
 
1015
        trailer[17] = 0x33;
 
1016
        trailer[18] = 0x00;
 
1017
        trailer[19] = 0x00;
 
1018
        trailer[20] = 0x00;
 
1019
        trailer[21] = 0x00;
 
1020
        trailer[22] = 0x00;
 
1021
        trailer[23] = 0x33;
 
1022
 
 
1023
        fwrite(trailer, 8, 3, gendata.stream);
1027
1024
}
1028
1025
 
1029
1026
/* Output a "page forward" escape sequence,
1035
1032
static void
1036
1033
skiplines(int skiprow, int skipin)
1037
1034
{
1038
 
        byte escape[8];
1039
 
        int vskip;
1040
 
 
1041
 
        /* The vertical skip command accepts a spacing expressed in 
1042
 
         * 1200ths of an inch, so we must convert lines to 1200ths 
1043
 
         * of an inch. After the conversion we sum an offset directly 
1044
 
         * expressed in 1200ths of an inch: this way we can use this
1045
 
         * routine to skip both a certain amount of lines (which exact
1046
 
         * spacing value depends on the vertical resolution) and a 
1047
 
         * fixed offset that we directly know in spacing units.
1048
 
         */ 
1049
 
        vskip = skiprow*gendata.yrmul + skipin;
1050
 
        
1051
 
        escape[0] = 0x1b;
1052
 
        escape[1] = 0x23;
1053
 
        escape[2] = 0x80;
1054
 
        escape[3] = vskip >> 8;
1055
 
        escape[4] = vskip & 0xff;
1056
 
        escape[5] = 0x00;
1057
 
        escape[6] = 0x00;
1058
 
        escape[7] = calccheck8(escape);
1059
 
 
1060
 
        /* Adjust the number of lines still inside the printer */
1061
 
        gendata.linetoeject -= vskip;
1062
 
        
1063
 
        fwrite(escape, 8, 1, gendata.stream);
1064
 
}       
 
1035
        byte escape[8];
 
1036
        int vskip;
 
1037
 
 
1038
        /* The vertical skip command accepts a spacing expressed in
 
1039
         * 1200ths of an inch, so we must convert lines to 1200ths
 
1040
         * of an inch. After the conversion we sum an offset directly
 
1041
         * expressed in 1200ths of an inch: this way we can use this
 
1042
         * routine to skip both a certain amount of lines (which exact
 
1043
         * spacing value depends on the vertical resolution) and a
 
1044
         * fixed offset that we directly know in spacing units.
 
1045
         */
 
1046
        vskip = skiprow*gendata.yrmul + skipin;
 
1047
 
 
1048
        escape[0] = 0x1b;
 
1049
        escape[1] = 0x23;
 
1050
        escape[2] = 0x80;
 
1051
        escape[3] = vskip >> 8;
 
1052
        escape[4] = vskip & 0xff;
 
1053
        escape[5] = 0x00;
 
1054
        escape[6] = 0x00;
 
1055
        escape[7] = calccheck8(escape);
 
1056
 
 
1057
        /* Adjust the number of lines still inside the printer */
 
1058
        gendata.linetoeject -= vskip;
 
1059
 
 
1060
        fwrite(escape, 8, 1, gendata.stream);
 
1061
}
1065
1062
 
1066
1063
/* Fill a stripe header with data.
1067
1064
 *
1072
1069
 * bytes:    total number of bytes in the stripe, including directories
1073
1070
 *           (but excluding the 24 bytes of the header).
1074
1071
 */
1075
 
static void 
 
1072
static void
1076
1073
fillheader(int head, int numcol, int firstcol, int bytes)
1077
1074
{
1078
 
        int len, offs1, startabs;
1079
 
        int endabs, select, fwd;
1080
 
        int back, nabspos, sep;
1081
 
        byte *header;
1082
 
 
1083
 
        header = gendata.header;
1084
 
        
1085
 
        /* Correct the measures: firstcol and len need to 
1086
 
         * be in 1200ths of an inch.
1087
 
         */
1088
 
        firstcol *= gendata.xrmul;
1089
 
        len = numcol * gendata.xrmul;
1090
 
        
1091
 
        /* Alter select to choose direction */
1092
 
        select = gendata.select | (gendata.direction == LEFT ? 0x01 : 0x00);
1093
 
 
1094
 
        /* Calculate the proper horizontal offset */
1095
 
        offs1 = hoffset[head][gendata.direction];
1096
 
 
1097
 
        /* Now calculate the correct separation depending on the
1098
 
         * head type and adjust "select" to choose between left
1099
 
         * or right head.
1100
 
         */
1101
 
        if(head == LEFT)
1102
 
        {
1103
 
                sep = (gendata.bwsep * 2) / gendata.xrmul;
1104
 
        }
1105
 
        else
1106
 
        {
1107
 
                sep = (gendata.colsep * 2) / gendata.xrmul;             
1108
 
                select |= 0x80;
1109
 
        }
1110
 
 
1111
 
        /* Now calculate absolute starting and ending positions
1112
 
         * of this stripe, taking into account the printing direction
1113
 
         */
1114
 
        startabs = firstcol + offs1;
1115
 
 
1116
 
        if(gendata.direction == LEFT)
1117
 
                endabs = startabs + len;
1118
 
        else
1119
 
                endabs = startabs - len;
1120
 
 
1121
 
        /* And now, basing on current head position,
1122
 
         * transform the absolute coordinates in a
1123
 
         * relative movement of the head.
1124
 
         * The formulas used for this are "black magic",
1125
 
         * since this is a part of the protocol which is
1126
 
         * still not well known. What you see here is an
1127
 
         * empyrical formula devised by examination and 
1128
 
         * parameter fitting on the data output by the
1129
 
         * Windows driver.
1130
 
         */
1131
 
        if(gendata.direction == LEFT)
1132
 
        {
1133
 
                nabspos = (((endabs - 3600) >> 3) & 0xfff0) + 9;
1134
 
                fwd = nabspos - gendata.curheadpos;
1135
 
        }
1136
 
        else
1137
 
        {
1138
 
                if(endabs > 4816)
1139
 
                        nabspos = (((endabs - 4800) >> 3) & 0xfff0) + 9;
1140
 
                else
1141
 
                        nabspos = (((endabs - 3600) >> 3) & 0xfff0) + 9;
1142
 
                fwd = gendata.curheadpos - nabspos;
1143
 
        }
1144
 
 
1145
 
        gendata.curheadpos += (gendata.direction == LEFT ? fwd : -fwd);
1146
 
 
1147
 
        /* If we are printing unidirectionally, calculate
1148
 
         * the backward movement to return the printing head
1149
 
         * at the beginning of this stripe.
1150
 
         */
1151
 
        back = 0;
1152
 
        if(gendata.bidirprint == FALSE)
1153
 
        {
1154
 
                if(startabs > 4816)
1155
 
                        nabspos = ((startabs - 4800) >> 3) & 0xfff0;
1156
 
                else
1157
 
                        nabspos = ((startabs - 3600) >> 3) & 0xfff0;     
1158
 
 
1159
 
                if(gendata.direction == LEFT)
1160
 
                        back = gendata.curheadpos - nabspos;
1161
 
                else
1162
 
                        back = nabspos - gendata.curheadpos;
1163
 
        }
1164
 
 
1165
 
        gendata.curheadpos -= (gendata.direction == LEFT ? back : -back);
1166
 
 
1167
 
        /* First part of the header */
1168
 
        header[0] = 0x1b;
1169
 
        header[1] = 0x40;
1170
 
        header[2] = select;        /* Printing type flags */
1171
 
        header[3] = numcol >> 8;   /* MSB of the number of columns to print */
1172
 
        header[4] = numcol & 0xff; /* LSB of the number of columns to print */
1173
 
        header[5] = fwd >> 8;      /* MSB of the relative forward head motion */
1174
 
        header[6] = fwd & 0xff;    /* LSB of the relative forward head motion */
1175
 
        header[7] = calccheck8(&header[0]);
1176
 
        
1177
 
        /* Second part of the header */
1178
 
        header[8] = 0x1b;
1179
 
        header[9] = 0x42;
1180
 
        header[10] = 0x00;
1181
 
        if(gendata.modelprint==1) header[10] = 0x10; /* Lexmark Z12 protocol */
1182
 
        header[11] = back >> 8;  /* MSB of the relative backward head motion */
1183
 
        header[12] = back & 0xff;  /* LSB of the relative backward head motion */
1184
 
        header[13] = 0x00;  /* MSB of the relative downward head motion */
1185
 
        header[14] = 0x00;  /* LSB of the relative downward head motion */
1186
 
        header[15] = calccheck8(&header[8]);
1187
 
        
1188
 
        /* Third (and last) part of the header */
1189
 
        header[16] = 0x1b;
1190
 
        header[17] = 0x43;
1191
 
        header[18] = (bytes >> 16) & 0xff;
1192
 
        header[19] = (bytes >> 8) & 0xff; 
1193
 
        header[20] = bytes & 0xff;    /* LSB of the number of bytes in this stripe */
1194
 
        header[21] = startabs >> 8;   /* MSB of the starting column of this stripe */
1195
 
        header[22] = startabs & 0xff; /* LSB of the starting column of this stripe */
1196
 
        header[23] = calccheck8(&header[16]);
1197
 
 
1198
 
        /* Signal to other routines that the output buffer
1199
 
         * is full and how many bytes it is long.
1200
 
         */
1201
 
        gendata.stripebytes = bytes;
1202
 
        gendata.fullflag = TRUE;
1203
 
 
1204
 
        /* If bidirectional printing is in effect, change 
1205
 
         * the printing direction for the next stripe
1206
 
         */
1207
 
        if(gendata.bidirprint)
1208
 
                gendata.direction = (gendata.direction == LEFT ? RIGHT : LEFT);
 
1075
        int len, offs1, startabs;
 
1076
        int endabs, select, fwd;
 
1077
        int back, nabspos, sep;
 
1078
        byte *header;
 
1079
 
 
1080
        header = gendata.header;
 
1081
 
 
1082
        /* Correct the measures: firstcol and len need to
 
1083
         * be in 1200ths of an inch.
 
1084
         */
 
1085
        firstcol *= gendata.xrmul;
 
1086
        len = numcol * gendata.xrmul;
 
1087
 
 
1088
        /* Alter select to choose direction */
 
1089
        select = gendata.select | (gendata.direction == LEFT ? 0x01 : 0x00);
 
1090
 
 
1091
        /* Calculate the proper horizontal offset */
 
1092
        offs1 = hoffset[head][gendata.direction];
 
1093
 
 
1094
        /* Now calculate the correct separation depending on the
 
1095
         * head type and adjust "select" to choose between left
 
1096
         * or right head.
 
1097
         */
 
1098
        if(head == LEFT)
 
1099
        {
 
1100
                sep = (gendata.bwsep * 2) / gendata.xrmul;
 
1101
        }
 
1102
        else
 
1103
        {
 
1104
                sep = (gendata.colsep * 2) / gendata.xrmul;
 
1105
                select |= 0x80;
 
1106
        }
 
1107
 
 
1108
        /* Now calculate absolute starting and ending positions
 
1109
         * of this stripe, taking into account the printing direction
 
1110
         */
 
1111
        startabs = firstcol + offs1;
 
1112
 
 
1113
        if(gendata.direction == LEFT)
 
1114
                endabs = startabs + len;
 
1115
        else
 
1116
                endabs = startabs - len;
 
1117
 
 
1118
        /* And now, basing on current head position,
 
1119
         * transform the absolute coordinates in a
 
1120
         * relative movement of the head.
 
1121
         * The formulas used for this are "black magic",
 
1122
         * since this is a part of the protocol which is
 
1123
         * still not well known. What you see here is an
 
1124
         * empyrical formula devised by examination and
 
1125
         * parameter fitting on the data output by the
 
1126
         * Windows driver.
 
1127
         */
 
1128
        if(gendata.direction == LEFT)
 
1129
        {
 
1130
                nabspos = (((endabs - 3600) >> 3) & 0xfff0) + 9;
 
1131
                fwd = nabspos - gendata.curheadpos;
 
1132
        }
 
1133
        else
 
1134
        {
 
1135
                if(endabs > 4816)
 
1136
                        nabspos = (((endabs - 4800) >> 3) & 0xfff0) + 9;
 
1137
                else
 
1138
                        nabspos = (((endabs - 3600) >> 3) & 0xfff0) + 9;
 
1139
                fwd = gendata.curheadpos - nabspos;
 
1140
        }
 
1141
 
 
1142
        gendata.curheadpos += (gendata.direction == LEFT ? fwd : -fwd);
 
1143
 
 
1144
        /* If we are printing unidirectionally, calculate
 
1145
         * the backward movement to return the printing head
 
1146
         * at the beginning of this stripe.
 
1147
         */
 
1148
        back = 0;
 
1149
        if(gendata.bidirprint == FALSE)
 
1150
        {
 
1151
                if(startabs > 4816)
 
1152
                        nabspos = ((startabs - 4800) >> 3) & 0xfff0;
 
1153
                else
 
1154
                        nabspos = ((startabs - 3600) >> 3) & 0xfff0;
 
1155
 
 
1156
                if(gendata.direction == LEFT)
 
1157
                        back = gendata.curheadpos - nabspos;
 
1158
                else
 
1159
                        back = nabspos - gendata.curheadpos;
 
1160
        }
 
1161
 
 
1162
        gendata.curheadpos -= (gendata.direction == LEFT ? back : -back);
 
1163
 
 
1164
        /* First part of the header */
 
1165
        header[0] = 0x1b;
 
1166
        header[1] = 0x40;
 
1167
        header[2] = select;        /* Printing type flags */
 
1168
        header[3] = numcol >> 8;   /* MSB of the number of columns to print */
 
1169
        header[4] = numcol & 0xff; /* LSB of the number of columns to print */
 
1170
        header[5] = fwd >> 8;      /* MSB of the relative forward head motion */
 
1171
        header[6] = fwd & 0xff;    /* LSB of the relative forward head motion */
 
1172
        header[7] = calccheck8(&header[0]);
 
1173
 
 
1174
        /* Second part of the header */
 
1175
        header[8] = 0x1b;
 
1176
        header[9] = 0x42;
 
1177
        header[10] = 0x00;
 
1178
        if(gendata.modelprint==1) header[10] = 0x10; /* Lexmark Z12 protocol */
 
1179
        header[11] = back >> 8;  /* MSB of the relative backward head motion */
 
1180
        header[12] = back & 0xff;  /* LSB of the relative backward head motion */
 
1181
        header[13] = 0x00;  /* MSB of the relative downward head motion */
 
1182
        header[14] = 0x00;  /* LSB of the relative downward head motion */
 
1183
        header[15] = calccheck8(&header[8]);
 
1184
 
 
1185
        /* Third (and last) part of the header */
 
1186
        header[16] = 0x1b;
 
1187
        header[17] = 0x43;
 
1188
        header[18] = (bytes >> 16) & 0xff;
 
1189
        header[19] = (bytes >> 8) & 0xff;
 
1190
        header[20] = bytes & 0xff;    /* LSB of the number of bytes in this stripe */
 
1191
        header[21] = startabs >> 8;   /* MSB of the starting column of this stripe */
 
1192
        header[22] = startabs & 0xff; /* LSB of the starting column of this stripe */
 
1193
        header[23] = calccheck8(&header[16]);
 
1194
 
 
1195
        /* Signal to other routines that the output buffer
 
1196
         * is full and how many bytes it is long.
 
1197
         */
 
1198
        gendata.stripebytes = bytes;
 
1199
        gendata.fullflag = TRUE;
 
1200
 
 
1201
        /* If bidirectional printing is in effect, change
 
1202
         * the printing direction for the next stripe
 
1203
         */
 
1204
        if(gendata.bidirprint)
 
1205
                gendata.direction = (gendata.direction == LEFT ? RIGHT : LEFT);
1209
1206
}
1210
1207
 
1211
 
/* Set final information in the header and output all 
 
1208
/* Set final information in the header and output all
1212
1209
 * the data passes. This routine is needed because the
1213
1210
 * actual values of two fields of the header (final
1214
1211
 * head position and number of vertical lines to reach
1218
1215
 * vskip  : number of lines to skip to reach next stripe
1219
1216
 * newhead: head used for the next stripe (LEFT or RIGHT)
1220
1217
 */
1221
 
static void 
 
1218
static void
1222
1219
finalizeheader(int vskip, int newhead)
1223
1220
{
1224
 
        int offs2, nstartabs, back, fwd;
1225
 
        int habs, p, dir, endabs, col;
1226
 
        int newstart, sep;
1227
 
        byte *header;
1228
 
 
1229
 
        header = gendata.header;
1230
 
 
1231
 
        /* Check the printing direction this stripe
1232
 
         * was originally intended for.
1233
 
         */
1234
 
        dir = (header[2] & 0x01 ? LEFT : RIGHT);
1235
 
 
1236
 
        /* Retrieve the horizontal offset for the next stripe */
1237
 
        offs2 = hoffset[newhead][gendata.direction];
1238
 
 
1239
 
        /* Calculate the separation adjust in 1200ths of an inch */
1240
 
        if(newhead == LEFT)
1241
 
                sep = (gendata.bwsep * 2) / gendata.xrmul;
1242
 
        else
1243
 
                sep = (gendata.colsep * 2) / gendata.xrmul;
1244
 
 
1245
 
        /* Now calculate the correct starting column
1246
 
         * of the next stripe
1247
 
         */
1248
 
        if(gendata.direction == LEFT)
1249
 
                newstart = (gendata.left * gendata.xrmul) - sep;
1250
 
        else
1251
 
                newstart = (gendata.right * gendata.xrmul);
1252
 
        
1253
 
        vskip *= gendata.yrmul;
1254
 
        
1255
 
        /* Calculate absolute starting position of new stripe */
1256
 
        nstartabs = newstart + offs2;
1257
 
        
1258
 
        /* Calculate absolute ending position of this stripe 
1259
 
         * by summing (with proper sign) the starting position
1260
 
         * and the width.
1261
 
         */
1262
 
        endabs = header[21]*256 + header[22]; /* Starting position */
1263
 
        col = (header[3]*256 + header[4]); /* Width in columns */
1264
 
        col *= gendata.xrmul; /* Transformed in 1200ths of an inch */
1265
 
 
1266
 
        if(dir == LEFT)
1267
 
                endabs += col; /* Printing left-to-right */
1268
 
        else
1269
 
                endabs -= col; /* Printing right-to-left */
1270
 
 
1271
 
        /* Correct head position neutralizing the effect
1272
 
         * of the last issued head movement commands. The
1273
 
         * head movement for this stripe needs to be
1274
 
         * recalculated from scratch to take into account        
1275
 
         * the correct beginning position of the next stripe.
1276
 
         */
1277
 
        if(dir == LEFT)
1278
 
        {
1279
 
                gendata.curheadpos += header[11]*256 + header[12]; /* Back movement */
1280
 
                gendata.curheadpos -= header[5]*256 + header[6];   /* Forward movement */
1281
 
        }
1282
 
        else
1283
 
        {
1284
 
                gendata.curheadpos -= header[11]*256 + header[12]; /* Back movement */
1285
 
                gendata.curheadpos += header[5]*256 + header[6];   /* Forward movement */
1286
 
        }
1287
 
        
1288
 
        /* We use a convention of passing a negative value for
1289
 
         * "newhead" to mean that this is the last stripe of the
1290
 
         * sheet, so we don't need to care for the next stripe.
1291
 
         */
1292
 
        if(newhead < 0)
1293
 
        {
1294
 
                /* Last stripe: we only need to calculate proper forward 
1295
 
                 * motion to print all the current stripe.
1296
 
                 */
1297
 
                fwd = ((header[5]*256 + header[6]) & 0xfff0) + 9;
1298
 
        }
1299
 
        else
1300
 
        {
1301
 
                /* This is not the last stripe, so we need to calculate
1302
 
                 * the forward (in the printing direction) movement
1303
 
                 * that will take the printing head at the end of the
1304
 
                 * current stripe or at the beginning of the next, 
1305
 
                 * whichever is farther. Note that we are always 
1306
 
                 * talking relative to printing direction, so we must
1307
 
                 * take into proper account if we are printing from left
1308
 
                 * to right or from right to left.
1309
 
                 */
1310
 
                if(dir == LEFT)
1311
 
                {
1312
 
                        p = max(endabs, nstartabs);
1313
 
                        habs = (((p - 3600) >> 3) & 0xfff0) + 9;
1314
 
                        fwd = habs - gendata.curheadpos;
1315
 
 
1316
 
                        /* part for the Lexmark Z31!!! */
1317
 
                        if(gendata.modelprint==2) fwd += gendata.z31margin;
1318
 
 
1319
 
                }
1320
 
                else
1321
 
                {
1322
 
                        p = min(endabs, nstartabs);
1323
 
                        if(p > 4816)
1324
 
                                habs = (((p - 4800) >> 3) & 0xfff0);
1325
 
                        else
1326
 
                                habs = (((p - 3600) >> 3) & 0xfff0);                    
1327
 
                        fwd = gendata.curheadpos - habs;
1328
 
                }
1329
 
        }
1330
 
        
1331
 
        /* Now update the current head position to take into 
1332
 
         * account the forward movement just computed
1333
 
         */
1334
 
        gendata.curheadpos += (dir == LEFT ? fwd : -fwd);
1335
 
 
1336
 
        /* Now calculate the value of the needed backward movement 
1337
 
         * to poisition the head correctly for the start of the
1338
 
         * next stripe.
1339
 
         */
1340
 
        if(newhead < 0 || gendata.bidirprint)
1341
 
        {
1342
 
                /* If this is the last stripe of the page,
1343
 
                 * there is no need to take back the head:
1344
 
                 * it will be done by the parking command.
1345
 
                 * Or if we are printing bidirectionally,
1346
 
                 * the forward command has taken the head to
1347
 
                 * the correct position, so no need to move it.
1348
 
                 */
1349
 
                back = 0;
1350
 
        }
1351
 
        else
1352
 
        {
1353
 
                /* Calculate the right backward movement basing 
1354
 
                 * on the start of the next stripe.
1355
 
                 */
1356
 
                if(nstartabs > 4856)
1357
 
                        habs = ((nstartabs - 4840) >> 3) & 0xfff0;
1358
 
                else
1359
 
                        habs = ((nstartabs - 3600) >> 3) & 0xfff0;                      
1360
 
                
1361
 
                back = gendata.curheadpos - habs;
1362
 
 
1363
 
                /* If the next stripe starts at the right 
1364
 
                 * of this one, "back" will be too small or
1365
 
                 * negative, so correct it. 
1366
 
                 * It appears that 16 is the minimum allowable
1367
 
                 * backward movement that does not make the 3200
1368
 
                 * misbehave in the next stripe. This does not hold
1369
 
                 * if we are changing printing direction (in such a
1370
 
                 * case backward movement may be zero). This means
1371
 
                 * we are moving the head a little more than needed,
1372
 
                 * but it seems unavoidable.
1373
 
                 */
1374
 
                if(back < 16)back = 16;
1375
 
        }
 
1221
        int offs2, nstartabs, back, fwd;
 
1222
        int habs, p, dir, endabs, col;
 
1223
        int newstart, sep;
 
1224
        byte *header;
 
1225
 
 
1226
        header = gendata.header;
 
1227
 
 
1228
        /* Check the printing direction this stripe
 
1229
         * was originally intended for.
 
1230
         */
 
1231
        dir = (header[2] & 0x01 ? LEFT : RIGHT);
 
1232
 
 
1233
        /* Retrieve the horizontal offset for the next stripe */
 
1234
        offs2 = hoffset[newhead][gendata.direction];
 
1235
 
 
1236
        /* Calculate the separation adjust in 1200ths of an inch */
 
1237
        if(newhead == LEFT)
 
1238
                sep = (gendata.bwsep * 2) / gendata.xrmul;
 
1239
        else
 
1240
                sep = (gendata.colsep * 2) / gendata.xrmul;
 
1241
 
 
1242
        /* Now calculate the correct starting column
 
1243
         * of the next stripe
 
1244
         */
 
1245
        if(gendata.direction == LEFT)
 
1246
                newstart = (gendata.left * gendata.xrmul) - sep;
 
1247
        else
 
1248
                newstart = (gendata.right * gendata.xrmul);
 
1249
 
 
1250
        vskip *= gendata.yrmul;
 
1251
 
 
1252
        /* Calculate absolute starting position of new stripe */
 
1253
        nstartabs = newstart + offs2;
 
1254
 
 
1255
        /* Calculate absolute ending position of this stripe
 
1256
         * by summing (with proper sign) the starting position
 
1257
         * and the width.
 
1258
         */
 
1259
        endabs = header[21]*256 + header[22]; /* Starting position */
 
1260
        col = (header[3]*256 + header[4]); /* Width in columns */
 
1261
        col *= gendata.xrmul; /* Transformed in 1200ths of an inch */
 
1262
 
 
1263
        if(dir == LEFT)
 
1264
                endabs += col; /* Printing left-to-right */
 
1265
        else
 
1266
                endabs -= col; /* Printing right-to-left */
 
1267
 
 
1268
        /* Correct head position neutralizing the effect
 
1269
         * of the last issued head movement commands. The
 
1270
         * head movement for this stripe needs to be
 
1271
         * recalculated from scratch to take into account
 
1272
         * the correct beginning position of the next stripe.
 
1273
         */
 
1274
        if(dir == LEFT)
 
1275
        {
 
1276
                gendata.curheadpos += header[11]*256 + header[12]; /* Back movement */
 
1277
                gendata.curheadpos -= header[5]*256 + header[6];   /* Forward movement */
 
1278
        }
 
1279
        else
 
1280
        {
 
1281
                gendata.curheadpos -= header[11]*256 + header[12]; /* Back movement */
 
1282
                gendata.curheadpos += header[5]*256 + header[6];   /* Forward movement */
 
1283
        }
 
1284
 
 
1285
        /* We use a convention of passing a negative value for
 
1286
         * "newhead" to mean that this is the last stripe of the
 
1287
         * sheet, so we don't need to care for the next stripe.
 
1288
         */
 
1289
        if(newhead < 0)
 
1290
        {
 
1291
                /* Last stripe: we only need to calculate proper forward
 
1292
                 * motion to print all the current stripe.
 
1293
                 */
 
1294
                fwd = ((header[5]*256 + header[6]) & 0xfff0) + 9;
 
1295
        }
 
1296
        else
 
1297
        {
 
1298
                /* This is not the last stripe, so we need to calculate
 
1299
                 * the forward (in the printing direction) movement
 
1300
                 * that will take the printing head at the end of the
 
1301
                 * current stripe or at the beginning of the next,
 
1302
                 * whichever is farther. Note that we are always
 
1303
                 * talking relative to printing direction, so we must
 
1304
                 * take into proper account if we are printing from left
 
1305
                 * to right or from right to left.
 
1306
                 */
 
1307
                if(dir == LEFT)
 
1308
                {
 
1309
                        p = max(endabs, nstartabs);
 
1310
                        habs = (((p - 3600) >> 3) & 0xfff0) + 9;
 
1311
                        fwd = habs - gendata.curheadpos;
 
1312
 
 
1313
                        /* part for the Lexmark Z31!!! */
 
1314
                        if(gendata.modelprint==2) fwd += gendata.z31margin;
 
1315
 
 
1316
                }
 
1317
                else
 
1318
                {
 
1319
                        p = min(endabs, nstartabs);
 
1320
                        if(p > 4816)
 
1321
                                habs = (((p - 4800) >> 3) & 0xfff0);
 
1322
                        else
 
1323
                                habs = (((p - 3600) >> 3) & 0xfff0);
 
1324
                        fwd = gendata.curheadpos - habs;
 
1325
                }
 
1326
        }
 
1327
 
 
1328
        /* Now update the current head position to take into
 
1329
         * account the forward movement just computed
 
1330
         */
 
1331
        gendata.curheadpos += (dir == LEFT ? fwd : -fwd);
 
1332
 
 
1333
        /* Now calculate the value of the needed backward movement
 
1334
         * to poisition the head correctly for the start of the
 
1335
         * next stripe.
 
1336
         */
 
1337
        if(newhead < 0 || gendata.bidirprint)
 
1338
        {
 
1339
                /* If this is the last stripe of the page,
 
1340
                 * there is no need to take back the head:
 
1341
                 * it will be done by the parking command.
 
1342
                 * Or if we are printing bidirectionally,
 
1343
                 * the forward command has taken the head to
 
1344
                 * the correct position, so no need to move it.
 
1345
                 */
 
1346
                back = 0;
 
1347
        }
 
1348
        else
 
1349
        {
 
1350
                /* Calculate the right backward movement basing
 
1351
                 * on the start of the next stripe.
 
1352
                 */
 
1353
                if(nstartabs > 4856)
 
1354
                        habs = ((nstartabs - 4840) >> 3) & 0xfff0;
 
1355
                else
 
1356
                        habs = ((nstartabs - 3600) >> 3) & 0xfff0;
 
1357
 
 
1358
                back = gendata.curheadpos - habs;
 
1359
 
 
1360
                /* If the next stripe starts at the right
 
1361
                 * of this one, "back" will be too small or
 
1362
                 * negative, so correct it.
 
1363
                 * It appears that 16 is the minimum allowable
 
1364
                 * backward movement that does not make the 3200
 
1365
                 * misbehave in the next stripe. This does not hold
 
1366
                 * if we are changing printing direction (in such a
 
1367
                 * case backward movement may be zero). This means
 
1368
                 * we are moving the head a little more than needed,
 
1369
                 * but it seems unavoidable.
 
1370
                 */
 
1371
                if(back < 16)back = 16;
 
1372
        }
1376
1373
 
1377
1374
  /* Lastly, update the current head position with the
1378
 
         * backward movement just calculated.
1379
 
         */
1380
 
        gendata.curheadpos -= (dir == LEFT ? back : -back);
1381
 
 
1382
 
        /* Modify first part of the header */
1383
 
        header[5] = fwd >> 8;
1384
 
        header[6] = fwd & 0xff;
1385
 
        header[7] = calccheck8(&header[0]);
1386
 
 
1387
 
        /* Modify second part of the header */
1388
 
        header[8] = 0x1b;
1389
 
        header[9] = 0x42;
1390
 
        header[10] = 0x00;
1391
 
        if(gendata.modelprint==1) header[10] = 0x10; /* Lexmark Z12 protocol */
1392
 
        header[11] = back >> 8;    /* MSB of the relative backward head motion */
1393
 
        header[12] = back & 0xff;  /* LSB of the relative backward head motion */
1394
 
        header[13] = vskip >> 8;   /* MSB of the relative downward head motion */
1395
 
        header[14] = vskip & 0xff; /* LSB of the relative downward head motion */
1396
 
        header[15] = calccheck8(&header[8]);
1397
 
 
1398
 
        /* Now output the data, signalling that the output
1399
 
         * buffer is now empty.
1400
 
         */
1401
 
        fwrite(header, 3, 8, gendata.stream);
1402
 
        fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
1403
 
        gendata.fullflag = FALSE;
 
1375
         * backward movement just calculated.
 
1376
         */
 
1377
        gendata.curheadpos -= (dir == LEFT ? back : -back);
 
1378
 
 
1379
        /* Modify first part of the header */
 
1380
        header[5] = fwd >> 8;
 
1381
        header[6] = fwd & 0xff;
 
1382
        header[7] = calccheck8(&header[0]);
 
1383
 
 
1384
        /* Modify second part of the header */
 
1385
        header[8] = 0x1b;
 
1386
        header[9] = 0x42;
 
1387
        header[10] = 0x00;
 
1388
        if(gendata.modelprint==1) header[10] = 0x10; /* Lexmark Z12 protocol */
 
1389
        header[11] = back >> 8;    /* MSB of the relative backward head motion */
 
1390
        header[12] = back & 0xff;  /* LSB of the relative backward head motion */
 
1391
        header[13] = vskip >> 8;   /* MSB of the relative downward head motion */
 
1392
        header[14] = vskip & 0xff; /* LSB of the relative downward head motion */
 
1393
        header[15] = calccheck8(&header[8]);
 
1394
 
 
1395
        /* Now output the data, signalling that the output
 
1396
         * buffer is now empty.
 
1397
         */
 
1398
        fwrite(header, 3, 8, gendata.stream);
 
1399
        fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
 
1400
        gendata.fullflag = FALSE;
1404
1401
}
1405
1402
 
1406
 
/* Convert a buffer data stream into 
 
1403
/* Convert a buffer data stream into
1407
1404
 * directory/data representation, using the
1408
1405
 * shortest coding (either direct or RLE)
1409
1406
 *
1414
1411
static void
1415
1412
convbuf(int head, int numcols, int firstcol)
1416
1413
{
1417
 
        byte *read, *write;
1418
 
        int x, i, c, p, q, cnt, rle, std;
1419
 
        int nby, ofs, dts0, dtr0, dtr1;
1420
 
        int bytes;
1421
 
 
1422
 
        /* Initialize the pointers. We use the same buffer 
1423
 
         * for both input and output (we can do it because 
1424
 
         * the output data is at most as long as the input).
1425
 
         * Note that the encode routines skipped 4 bytes at
1426
 
         * each column to make room for the directory word.
1427
 
         */
1428
 
        read = gendata.outdata + 4;
1429
 
        write = gendata.outdata;
1430
 
 
1431
 
        /* Set the parameters that will be used to create the directory and 
1432
 
         * to access the data. These parameters define the structure of the 
1433
 
         * directory word (32 bit) and depend on the number of nozzles that 
1434
 
         * are used. Note that the directory bitfield is initialized to all 
1435
 
         * ones (but read below for further info) because it works in negative 
1436
 
         * logic (i.e. a change is marked by a zero bit).
1437
 
         * Below, nby is the number of bytes needed in the input data to map 
1438
 
         * a column (each nozzle is 1 bit, so 208 nozzles are 26 bytes and 
1439
 
         * 192 nozzles are 24 bytes). Ofs is the number of the first bit of 
1440
 
         * the directory bitfield in the directory word (with 208 nozzles we 
1441
 
         * need 26 bits, from 6 to 31, with 192 nozzles we need 24 bits, from 
1442
 
         * 8 to 31). The other three parameters are the values needed to 
1443
 
         * initialize the directory word properly: the key is the first two 
1444
 
         * bits, which must be "10" for a directly encoded stripe and "01" for 
1445
 
         * a RLE encoded one. In the lexmark directory, each bit represents a 
1446
 
         * group of 8 nozzles: in a directly encoded stripe if the bit is "1" 
1447
 
         * it means none of the nozzles in the group are used, if it is a "0" 
1448
 
         * it means at least one is used and we need to append a data byte to 
1449
 
         * define the exact usage pattern. So, for direct encoded stripes we 
1450
 
         * start with the first two bits set to "10" and all the directory
1451
 
         * bitfield set to "1" (we will unset to "0" only the needed bits in
1452
 
         * the encoding loop). If we are using RLE encoding, each "0" bits
1453
 
         * means that there is a data byte that defines a pattern for the 
1454
 
         * group of 8 nozzles associated to that bit, and an "1" means that 
1455
 
         * the pattern for the associated group of nozzles is the same as the
1456
 
         * previous group. This means that for RLE encoded stripes we start the
1457
 
         * directory word with two bits set to "01" and then initialize to "1"
1458
 
         * all the directory bitfield, except the first one which must be 0
1459
 
         * because we must have at least one data byte to define the initial
1460
 
         * pattern that will be eventually repeated.
1461
 
         */
1462
 
        if(gendata.numlines == 208)
1463
 
        {
1464
 
                nby = 26;    
1465
 
                ofs = 6;    
1466
 
                dts0 = 0x83; 
1467
 
                dtr0 = 0x41;
1468
 
                dtr1 = 0xff;
1469
 
        }
1470
 
        else
1471
 
        {
1472
 
                nby = 24;
1473
 
                ofs = 8;
1474
 
                dts0 = 0x80;
1475
 
                dtr0 = 0x40;
1476
 
                dtr1 = 0x7f;
1477
 
        }
1478
 
 
1479
 
        /* The variable "bytes" will contain the total 
1480
 
         * number of output bytes in the data stripe.
1481
 
         */
1482
 
        bytes = 0;
1483
 
 
1484
 
        /* For all the columns in the stripe */
1485
 
        for(x = 0; x < numcols; x++)
1486
 
        {
1487
 
                /* Calculate which representation is smaller by counting
1488
 
                 * the number of non zero data bytes for the direct encoding
1489
 
                 * and the number of changes between data bytes for the RLE.
1490
 
                 * At the end we have in "std" the length of the output data
1491
 
                 * if encoded with standard encoding, and in "rle" the length
1492
 
                 * of the output data if encoded with RLE.
1493
 
                 */
1494
 
                rle = 1;
1495
 
                c = read[0];
1496
 
                std = (c ? 1 : 0);
1497
 
                for(i=1; i<nby; i++)
1498
 
                {
1499
 
                        if((p = read[i]))std++;
1500
 
                        if(p != c)
1501
 
                        {
1502
 
                                rle++;
1503
 
                                c = read[i];
1504
 
                        }
1505
 
                }
1506
 
 
1507
 
                /* Now initialize the last two bytes in the directory
1508
 
                 * word. These always belong to the directory bitfield
1509
 
                 * and must be set to all ones.
1510
 
                 */
1511
 
                write[2] = 0xff;
1512
 
                write[3] = 0xff;
1513
 
 
1514
 
                /* And now encode the column, using the shortest encoding.
1515
 
                 * If the two encodings are of equal length we prefer the
1516
 
                 * standard encoding to the RLE one. No real reason for 
1517
 
                 * this: it could have been done the other way, but it
1518
 
                 * seems the Windows driver does this way as well...
1519
 
                 */
1520
 
                if(std > rle)
1521
 
                {
1522
 
                        /* Run-length encoding */
1523
 
 
1524
 
                        write[0] = dtr0;
1525
 
                        write[1] = dtr1;
1526
 
 
1527
 
                        p = read[0];
1528
 
                        write[4] = p;
1529
 
                        cnt = 5;
1530
 
                        q = ofs + 1;
1531
 
 
1532
 
                        for(i=1; i<nby; i++)
1533
 
                        {
1534
 
                                if(read[i] != p)
1535
 
                                {
1536
 
                                        p = read[i];
1537
 
                                        write[cnt] = p;
1538
 
                                        write[q>>3] &= ibits[q & 7];
1539
 
                                        cnt++;
1540
 
                                }
1541
 
                                q++;
1542
 
                        }
1543
 
                }
1544
 
                else
1545
 
                {
1546
 
                        /* Standard encoding */
1547
 
 
1548
 
                        write[0] = dts0;
1549
 
                        write[1] = 0xff;
1550
 
 
1551
 
                        cnt = 4;
1552
 
                        q = ofs;
1553
 
 
1554
 
                        for(i=0; i<nby; i++)
1555
 
                        {
1556
 
                                p = read[i];
1557
 
                                if(p)
1558
 
                                {
1559
 
                                        write[cnt] = p;
1560
 
                                        write[q>>3] &= ibits[q & 7];
1561
 
                                        cnt++;
1562
 
                                }
1563
 
                                q++;
1564
 
                        }
1565
 
                }
1566
 
 
1567
 
                /* Update the counters and pointers. Note that when 
1568
 
                 * we are here "cnt" is the number of bytes that we 
1569
 
                 * have actually output, including the directory word.
1570
 
                 */
1571
 
                read += (nby + 4);
1572
 
                write += cnt;
1573
 
                bytes += cnt;
1574
 
        }
1575
 
 
1576
 
        fillheader(head, numcols, firstcol, bytes);
 
1414
        byte *read, *write;
 
1415
        int x, i, c, p, q, cnt, rle, std;
 
1416
        int nby, ofs, dts0, dtr0, dtr1;
 
1417
        int bytes;
 
1418
 
 
1419
        /* Initialize the pointers. We use the same buffer
 
1420
         * for both input and output (we can do it because
 
1421
         * the output data is at most as long as the input).
 
1422
         * Note that the encode routines skipped 4 bytes at
 
1423
         * each column to make room for the directory word.
 
1424
         */
 
1425
        read = gendata.outdata + 4;
 
1426
        write = gendata.outdata;
 
1427
 
 
1428
        /* Set the parameters that will be used to create the directory and
 
1429
         * to access the data. These parameters define the structure of the
 
1430
         * directory word (32 bit) and depend on the number of nozzles that
 
1431
         * are used. Note that the directory bitfield is initialized to all
 
1432
         * ones (but read below for further info) because it works in negative
 
1433
         * logic (i.e. a change is marked by a zero bit).
 
1434
         * Below, nby is the number of bytes needed in the input data to map
 
1435
         * a column (each nozzle is 1 bit, so 208 nozzles are 26 bytes and
 
1436
         * 192 nozzles are 24 bytes). Ofs is the number of the first bit of
 
1437
         * the directory bitfield in the directory word (with 208 nozzles we
 
1438
         * need 26 bits, from 6 to 31, with 192 nozzles we need 24 bits, from
 
1439
         * 8 to 31). The other three parameters are the values needed to
 
1440
         * initialize the directory word properly: the key is the first two
 
1441
         * bits, which must be "10" for a directly encoded stripe and "01" for
 
1442
         * a RLE encoded one. In the lexmark directory, each bit represents a
 
1443
         * group of 8 nozzles: in a directly encoded stripe if the bit is "1"
 
1444
         * it means none of the nozzles in the group are used, if it is a "0"
 
1445
         * it means at least one is used and we need to append a data byte to
 
1446
         * define the exact usage pattern. So, for direct encoded stripes we
 
1447
         * start with the first two bits set to "10" and all the directory
 
1448
         * bitfield set to "1" (we will unset to "0" only the needed bits in
 
1449
         * the encoding loop). If we are using RLE encoding, each "0" bits
 
1450
         * means that there is a data byte that defines a pattern for the
 
1451
         * group of 8 nozzles associated to that bit, and an "1" means that
 
1452
         * the pattern for the associated group of nozzles is the same as the
 
1453
         * previous group. This means that for RLE encoded stripes we start the
 
1454
         * directory word with two bits set to "01" and then initialize to "1"
 
1455
         * all the directory bitfield, except the first one which must be 0
 
1456
         * because we must have at least one data byte to define the initial
 
1457
         * pattern that will be eventually repeated.
 
1458
         */
 
1459
        if(gendata.numlines == 208)
 
1460
        {
 
1461
                nby = 26;
 
1462
                ofs = 6;
 
1463
                dts0 = 0x83;
 
1464
                dtr0 = 0x41;
 
1465
                dtr1 = 0xff;
 
1466
        }
 
1467
        else
 
1468
        {
 
1469
                nby = 24;
 
1470
                ofs = 8;
 
1471
                dts0 = 0x80;
 
1472
                dtr0 = 0x40;
 
1473
                dtr1 = 0x7f;
 
1474
        }
 
1475
 
 
1476
        /* The variable "bytes" will contain the total
 
1477
         * number of output bytes in the data stripe.
 
1478
         */
 
1479
        bytes = 0;
 
1480
 
 
1481
        /* For all the columns in the stripe */
 
1482
        for(x = 0; x < numcols; x++)
 
1483
        {
 
1484
                /* Calculate which representation is smaller by counting
 
1485
                 * the number of non zero data bytes for the direct encoding
 
1486
                 * and the number of changes between data bytes for the RLE.
 
1487
                 * At the end we have in "std" the length of the output data
 
1488
                 * if encoded with standard encoding, and in "rle" the length
 
1489
                 * of the output data if encoded with RLE.
 
1490
                 */
 
1491
                rle = 1;
 
1492
                c = read[0];
 
1493
                std = (c ? 1 : 0);
 
1494
                for(i=1; i<nby; i++)
 
1495
                {
 
1496
                        if((p = read[i]))std++;
 
1497
                        if(p != c)
 
1498
                        {
 
1499
                                rle++;
 
1500
                                c = read[i];
 
1501
                        }
 
1502
                }
 
1503
 
 
1504
                /* Now initialize the last two bytes in the directory
 
1505
                 * word. These always belong to the directory bitfield
 
1506
                 * and must be set to all ones.
 
1507
                 */
 
1508
                write[2] = 0xff;
 
1509
                write[3] = 0xff;
 
1510
 
 
1511
                /* And now encode the column, using the shortest encoding.
 
1512
                 * If the two encodings are of equal length we prefer the
 
1513
                 * standard encoding to the RLE one. No real reason for
 
1514
                 * this: it could have been done the other way, but it
 
1515
                 * seems the Windows driver does this way as well...
 
1516
                 */
 
1517
                if(std > rle)
 
1518
                {
 
1519
                        /* Run-length encoding */
 
1520
 
 
1521
                        write[0] = dtr0;
 
1522
                        write[1] = dtr1;
 
1523
 
 
1524
                        p = read[0];
 
1525
                        write[4] = p;
 
1526
                        cnt = 5;
 
1527
                        q = ofs + 1;
 
1528
 
 
1529
                        for(i=1; i<nby; i++)
 
1530
                        {
 
1531
                                if(read[i] != p)
 
1532
                                {
 
1533
                                        p = read[i];
 
1534
                                        write[cnt] = p;
 
1535
                                        write[q>>3] &= ibits[q & 7];
 
1536
                                        cnt++;
 
1537
                                }
 
1538
                                q++;
 
1539
                        }
 
1540
                }
 
1541
                else
 
1542
                {
 
1543
                        /* Standard encoding */
 
1544
 
 
1545
                        write[0] = dts0;
 
1546
                        write[1] = 0xff;
 
1547
 
 
1548
                        cnt = 4;
 
1549
                        q = ofs;
 
1550
 
 
1551
                        for(i=0; i<nby; i++)
 
1552
                        {
 
1553
                                p = read[i];
 
1554
                                if(p)
 
1555
                                {
 
1556
                                        write[cnt] = p;
 
1557
                                        write[q>>3] &= ibits[q & 7];
 
1558
                                        cnt++;
 
1559
                                }
 
1560
                                q++;
 
1561
                        }
 
1562
                }
 
1563
 
 
1564
                /* Update the counters and pointers. Note that when
 
1565
                 * we are here "cnt" is the number of bytes that we
 
1566
                 * have actually output, including the directory word.
 
1567
                 */
 
1568
                read += (nby + 4);
 
1569
                write += cnt;
 
1570
                bytes += cnt;
 
1571
        }
 
1572
 
 
1573
        fillheader(head, numcols, firstcol, bytes);
1577
1574
}
1578
1575
 
1579
1576
/* This routine takes one full buffer of data and
1583
1580
static void
1584
1581
encode_bw_buf(void)
1585
1582
{
1586
 
        int left, right, x, y, nn, mod;
1587
 
        int nxp, yy, numcols, incr;
1588
 
        int dy, dy2, csep, pass, f1;
1589
 
        int f2, start, s1, s2, yincr;
1590
 
        int q, mask, lines;
1591
 
        byte *scan, *data;
1592
 
 
1593
 
        /* Set some parameters that depend on resolution and are
1594
 
         * used in the inner loop to select lines to print.
1595
 
         * We basically encode all the even nozzles in a loop and
1596
 
         * all the odd nozzles in another loop. The values of s1
1597
 
         * and s2 are the starting offset in the line buffer for
1598
 
         * the first and second loop, and yincr is the number of lines
1599
 
         * in the buffer we move on at each cycle.
1600
 
         */ 
1601
 
        switch(gendata.yres)
1602
 
        {
1603
 
                /* At 300 dpi we use only one nozzle column, and
1604
 
                 * each line in the buffer is printed. So both offsets
1605
 
                 * are zero (only one is used, actually) and yincr is 1.
1606
 
                 * The mask is set to 127 because the buffer is 128 lines.
1607
 
                 */
1608
 
                case 300:
1609
 
                        yincr = 1;
1610
 
                        s1 = 0;
1611
 
                        s2 = 0;
1612
 
                        mask = 127;
1613
 
                        break;
1614
 
                        
1615
 
                /* At 600 dpi we use both nozzle columns: each row goes
1616
 
                 * alternatively to the left or right nozzle column. So
1617
 
                 * the even offset is zero, the odd offset is 1 and the
1618
 
                 * increment is 2: in this way the even loop scans lines
1619
 
                 * 0, 2, 4, ... and the odd loop lines 1, 3, 5, ...
1620
 
                 * Here the buffer is 256 lines so mask is set to 255.
1621
 
                 */
1622
 
                default:
1623
 
                case 600:
1624
 
                        yincr = 2;
1625
 
                        s1 = 0;
1626
 
                        s2 = 1;
1627
 
                        mask = 255;
1628
 
                        break;
1629
 
                        
1630
 
                /* At 1200 dpi we are printing two interleaved passes. Each
1631
 
                 * nozzle column sees every fourth line in the buffer (so
1632
 
                 * yincr is 4) and the starting offset varies depending on
1633
 
                 * which interleaved pass we are doing. 
1634
 
                 * During the first pass, even nozzles are used to print 
1635
 
                 * lines 0, 4, 8, ... and odd nozzles are used to print
1636
 
                 * lines 2, 6, 10, ... while in the second pass the even
1637
 
                 * nozzles print lines 1, 5, 9, ... and the odd nozzles
1638
 
                 * print lines 3, 7, 11, ...
1639
 
                 * The buffer is 512 lines, so mask is set to 511 */
1640
 
                case 1200:
1641
 
                        yincr = 4;
1642
 
                        s1 = (gendata.ileave ? 1 : 0);
1643
 
                        s2 = (gendata.ileave ? 3 : 2);
1644
 
                        mask = 511;
1645
 
                        break;
1646
 
        }
1647
 
        
1648
 
        /* Now we must calculate the offset q from the beginning of
1649
 
         * the buffer of the first line to print in this pass, and
1650
 
         * the total number of lines to be printed. We print as many
1651
 
         * lines as we can in a single pass, i.e. the value of "lines"
1652
 
         * is simply the number of lines that at the current vertical
1653
 
         * resolution fully cover the printing pen.
1654
 
         * Note that in case of monochrome printing we print all
1655
 
         * buffer lines, from first to last, so we also need to set
1656
 
         * the mask to a neutral value because we don't use wrapping.
1657
 
         */
1658
 
        if(gendata.rendermode == LXM3200_M)
1659
 
        {
1660
 
                mask = 511;
1661
 
                q = 0;
1662
 
                lines = gendata.numblines;
1663
 
        }
1664
 
        else
1665
 
        {
1666
 
                q = gendata.firstline + valign[BLACKVALIGN];
1667
 
                lines = (BWCOLPEN * 2) / gendata.yrmul;
1668
 
        }
1669
 
 
1670
 
        /* Adjust the value of the nozzle column separation to the
1671
 
         * horizontal resolution we are using now.
1672
 
         */
1673
 
        csep = (gendata.bwsep * 2) / gendata.xrmul;
1674
 
 
1675
 
        /* Here we calculate how many "real" passes we are doing.
1676
 
         * A "real" pass is a pass where a full column is printed
1677
 
         * and then some columns (maybe zero) are skipped before 
1678
 
         * printing another one. If we are at 1200 dpi horizontal
1679
 
         * then we must use only one nozzle column at a time, so each
1680
 
         * real pass comprises two subpasses, one where we print with
1681
 
         * even nozzles only and another where we print with odd
1682
 
         * nozzles only. So at 1200 dpi the "real" passes are half the
1683
 
         * total number of passes. Another way of looking at it: the
1684
 
         * "nxp" variable holds the separation, in columns, between two
1685
 
         * dot columns printed in the same head sweep.
1686
 
         */
1687
 
        nxp = gendata.numpasses;
1688
 
        if(gendata.xres == 1200)nxp /= 2; 
1689
 
 
1690
 
        /* Now calculate the byte increments for the *output* data
1691
 
         * buffer (i.e. the encoded buffer). The first variable,
1692
 
         * dy, is the number of bytes taken by a single data burst
1693
 
         * (both even and odd nozzle columns). The second variable,
1694
 
         * dy2, tells how many bytes we must skip from one column
1695
 
         * to the other (if we are printing multipass we skip some
1696
 
         * columns that will be printed in subsequent passes).
1697
 
         */
1698
 
        dy = (gendata.numlines / 8) + 4;
1699
 
        dy2 = dy * nxp;
1700
 
 
1701
 
        /* Calculate the starting and ending horizontal positions for
1702
 
         * this head pass. There are the margins corrected to take
1703
 
         * into account the displacement between the odd and even
1704
 
         * nozzle columns (csep). Moreover we start "csep" pixels
1705
 
         * before the margin to give the head a little more room to
1706
 
         * accelerate properly (not sure if this really works, but it
1707
 
         * doesn't cost much, so I've left it in).
1708
 
         */
1709
 
        if(gendata.direction == LEFT)
1710
 
        {
1711
 
                left = gendata.left - 2*csep;
1712
 
                right = gendata.right + csep;
1713
 
        }
1714
 
        else
1715
 
        {
1716
 
                left = gendata.left - csep;
1717
 
                right = gendata.right + 2*csep;
1718
 
        }
1719
 
        
1720
 
        /* Number of columns in a full row */
1721
 
        numcols = right - left;
1722
 
 
1723
 
        /* Calculate the last pixel of the first pass of the
1724
 
         * stripe. If we are printing bidirectionally, this 
1725
 
         * will be the base to calculate the start of the 
1726
 
         * passes printed right-to-left.
1727
 
         */ 
1728
 
        mod = numcols - (numcols % nxp);
1729
 
        
1730
 
        /* f1 and f2 are two flags that define which nozzle columns 
1731
 
         * we are using in this stripe, f1 for the even nozzle column 
1732
 
         * and f2 for the odd nozzle column: if they are zero that 
1733
 
         * nozzle column is not used in this pass.
1734
 
         */
1735
 
        f1 = 1;
1736
 
        f2 = 1;
1737
 
        if(gendata.yres == 300)
1738
 
        {
1739
 
                /* At 300 dpi we use only one nozzle column. As of now this 
1740
 
                 * is always the even one, but maybe it could be tried to 
1741
 
                 * alternate between columns at each pass, to improve the 
1742
 
                 * output quality.
1743
 
                 */
1744
 
                f1 = 1;
1745
 
                f2 = 0;
1746
 
        }
1747
 
        
1748
 
        /* Now start the passes to fill all the stripe */
1749
 
        for(pass = 0; pass < gendata.numpasses; pass++)
1750
 
        {
1751
 
                /* If there is data in the buffer which has not been
1752
 
                 * sent to the printer yet, send it now.
1753
 
                 */
1754
 
                if(gendata.fullflag)
1755
 
                {
1756
 
                        fwrite(gendata.header, 3, 8, gendata.stream);
1757
 
                        fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
1758
 
                        gendata.fullflag = FALSE;
1759
 
                }
1760
 
                
1761
 
                /* Clear the output buffer to avoid problems with the bitwise
1762
 
                 * operations we will do later on.
1763
 
                 */
1764
 
                memset(gendata.outdata, 0, gendata.numbytes * 30);
1765
 
                
1766
 
                /* Calculate standard increments, starting column
1767
 
                 * and start of output data. They will be corrected
1768
 
                 * later for 1200dpi or right-to-left printing direction.
1769
 
                 */
1770
 
                incr = nxp;
1771
 
                start = left + pass;
1772
 
                data = gendata.outdata + (pass*dy) + 4;
1773
 
                
1774
 
                /* It appears that at 1200dpi, in addition of not being able 
1775
 
                 * to use 208 nozzles mode for the black cartridge, the Lexmark 
1776
 
                 * 3200 cannot print at full rate with all the 192 useable nozzles.
1777
 
                 * Maybe the reason is that the data rate of 1200dpi horizontal
1778
 
                 * resolution exceeds the mechanical/thermal limits of the heads.
1779
 
                 * So if we are printing at 1200dpi we need to use alternatively
1780
 
                 * only odd or even numbered nozzles, for each printed column, to 
1781
 
                 * half the data rate towards the head.
1782
 
                 * This obviously means that, at 1200dpi horizontal, a minimum of
1783
 
                 * two passes are required to print each stripe. Since if we are 
1784
 
                 * printing at 1200dpi vertical we need two interlaced passes, a 
1785
 
                 * minimum grand total of 4 passes are needed to print one full 
1786
 
                 * 1200x1200 dpi stripe with the Lexmark 3200.
1787
 
                 */
1788
 
                if(gendata.xres == 1200)
1789
 
                {
1790
 
                        f1 = pass & 1;
1791
 
                        f2 = 1 - f1;
1792
 
                        
1793
 
                        start = left + (pass/2);
1794
 
                        data = gendata.outdata + ((pass/2)*dy) + 4;
1795
 
                }
1796
 
                
1797
 
                /* If printing right-to-left we need to present data
1798
 
                 * to the printer in that direction, inverting the
1799
 
                 * normal flow of data.
1800
 
                 */
1801
 
                if(gendata.direction == RIGHT)
1802
 
                {
1803
 
                        incr = -nxp;
1804
 
                        start += mod;
1805
 
                }
1806
 
                
1807
 
                /* Start column scanning */
1808
 
                x = start;
1809
 
 
1810
 
                /* Now we split the behaviour depending on the printing
1811
 
                 * direction. To be honest, the inner loops are almost
1812
 
                 * identical between left-to-right and right-to-left
1813
 
                 * directions. The only difference is where is computed
1814
 
                 * the contribute of the nozzle columns separation ("csep"), 
1815
 
                 * but having the "if" outside the loop it's somehow better.
1816
 
                 */
1817
 
                if(gendata.direction == LEFT)
1818
 
                {
1819
 
                        /* For all the columns in this pass */
1820
 
                        for(nn = 0; nn < numcols; nn += nxp)
1821
 
                        {
1822
 
                                /* Encode the even numbered nozzles */
1823
 
                                if((x >= 0) && f1)
1824
 
                                {
1825
 
                                        scan = gendata.scanbuf + x;
1826
 
                                        yy = 0;
1827
 
                                        for(y = s1; y < lines; y += yincr)
1828
 
                                        {
1829
 
                                                if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
1830
 
                                                        data[yy/8] |= bits[yy&7];
1831
 
                                                yy += 2;
1832
 
                                        }
1833
 
                                }
1834
 
                                
1835
 
                                /* Encode the odd numbered nozzles */ 
1836
 
                                if(((x+csep) < gendata.numbytes) && f2)
1837
 
                                {
1838
 
                                        scan = gendata.scanbuf + x + csep;
1839
 
                                        yy = 1;
1840
 
                                        for(y = s2; y < lines; y += yincr)
1841
 
                                        {
1842
 
                                                if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
1843
 
                                                        data[yy/8] |= bits[yy&7];
1844
 
                                                yy += 2;
1845
 
                                        }
1846
 
                                }
1847
 
 
1848
 
                                /* If we are in 1200dpi horizontal resolution,
1849
 
                                 * alternate between nozzle columns to avoid
1850
 
                                 * overstressing the printing head.
1851
 
                                 */
1852
 
                                if(gendata.xres == 1200)
1853
 
                                {
1854
 
                                        f1 = 1 - f1;
1855
 
                                        f2 = 1 - f2;
1856
 
                                }
1857
 
                                
1858
 
                                /* Adjust data pointers */
1859
 
                                data += dy2;
1860
 
                                x += incr;
1861
 
                        }
1862
 
                }                       
1863
 
                else /* direction == RIGHT */
1864
 
                {
1865
 
                        /* For all the columns in this pass */
1866
 
                        for(nn = 0; nn < numcols; nn += nxp)
1867
 
                        {                       
1868
 
                                /* Encode the odd numbered nozzles */ 
1869
 
                                if((x < gendata.numbytes) && f1)
1870
 
                                {
1871
 
                                        scan = gendata.scanbuf + x;
1872
 
                                        yy = 1;
1873
 
                                        for(y = s1; y < lines; y += yincr)
1874
 
                                        {
1875
 
                                                if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
1876
 
                                                        data[yy/8] |= bits[yy&7];
1877
 
                                                yy += 2;
1878
 
                                        }
1879
 
                                }
1880
 
 
1881
 
                                /* Encode the even numbered nozzles */                          
1882
 
                                if(((x-csep) >= 0) && f2)
1883
 
                                {
1884
 
                                        scan = gendata.scanbuf + x - csep;
1885
 
                                        yy = 0;
1886
 
                                        for(y = s2; y < lines; y += yincr)
1887
 
                                        {
1888
 
                                                if(scan[((y+q) & mask)*gendata.numbytes] & BLACK)
1889
 
                                                        data[yy/8] |= bits[yy&7];
1890
 
                                                yy += 2;
1891
 
                                        }
1892
 
                                }
1893
 
 
1894
 
                                /* If we are in 1200dpi horizontal resolution,
1895
 
                                 * alternate between nozzle columns to avoid 
1896
 
                                 * overstressing the printing head.
1897
 
                                 */
1898
 
                                if(gendata.xres == 1200)
1899
 
                                {
1900
 
                                        f1 = 1 - f1;
1901
 
                                        f2 = 1 - f2;
1902
 
                                }
1903
 
                                
1904
 
                                /* Adjust data pointers */
1905
 
                                data += dy2;
1906
 
                                x += incr;
1907
 
                        }
1908
 
                }
1909
 
 
1910
 
                /* Convert the buffer to the shortest output format.
1911
 
                 * Which is the first column of the output depends 
1912
 
                 * on the printing direction: it will be the left
1913
 
                 * margin if we are printing left to right or the
1914
 
                 * right margin if we are printing right to left.
1915
 
                 */
1916
 
                if(gendata.direction == LEFT)
1917
 
                        convbuf(LEFT, numcols, left);
1918
 
                else
1919
 
                        convbuf(LEFT, numcols, right);
1920
 
        }
 
1583
        int left, right, x, y, nn, mod;
 
1584
        int nxp, yy, numcols, incr;
 
1585
        int dy, dy2, csep, pass, f1;
 
1586
        int f2, start, s1, s2, yincr;
 
1587
        int q, mask, lines;
 
1588
        byte *scan, *data;
 
1589
 
 
1590
        /* Set some parameters that depend on resolution and are
 
1591
         * used in the inner loop to select lines to print.
 
1592
         * We basically encode all the even nozzles in a loop and
 
1593
         * all the odd nozzles in another loop. The values of s1
 
1594
         * and s2 are the starting offset in the line buffer for
 
1595
         * the first and second loop, and yincr is the number of lines
 
1596
         * in the buffer we move on at each cycle.
 
1597
         */
 
1598
        switch(gendata.yres)
 
1599
        {
 
1600
                /* At 300 dpi we use only one nozzle column, and
 
1601
                 * each line in the buffer is printed. So both offsets
 
1602
                 * are zero (only one is used, actually) and yincr is 1.
 
1603
                 * The mask is set to 127 because the buffer is 128 lines.
 
1604
                 */
 
1605
                case 300:
 
1606
                        yincr = 1;
 
1607
                        s1 = 0;
 
1608
                        s2 = 0;
 
1609
                        mask = 127;
 
1610
                        break;
 
1611
 
 
1612
                /* At 600 dpi we use both nozzle columns: each row goes
 
1613
                 * alternatively to the left or right nozzle column. So
 
1614
                 * the even offset is zero, the odd offset is 1 and the
 
1615
                 * increment is 2: in this way the even loop scans lines
 
1616
                 * 0, 2, 4, ... and the odd loop lines 1, 3, 5, ...
 
1617
                 * Here the buffer is 256 lines so mask is set to 255.
 
1618
                 */
 
1619
                default:
 
1620
                case 600:
 
1621
                        yincr = 2;
 
1622
                        s1 = 0;
 
1623
                        s2 = 1;
 
1624
                        mask = 255;
 
1625
                        break;
 
1626
 
 
1627
                /* At 1200 dpi we are printing two interleaved passes. Each
 
1628
                 * nozzle column sees every fourth line in the buffer (so
 
1629
                 * yincr is 4) and the starting offset varies depending on
 
1630
                 * which interleaved pass we are doing.
 
1631
                 * During the first pass, even nozzles are used to print
 
1632
                 * lines 0, 4, 8, ... and odd nozzles are used to print
 
1633
                 * lines 2, 6, 10, ... while in the second pass the even
 
1634
                 * nozzles print lines 1, 5, 9, ... and the odd nozzles
 
1635
                 * print lines 3, 7, 11, ...
 
1636
                 * The buffer is 512 lines, so mask is set to 511 */
 
1637
                case 1200:
 
1638
                        yincr = 4;
 
1639
                        s1 = (gendata.ileave ? 1 : 0);
 
1640
                        s2 = (gendata.ileave ? 3 : 2);
 
1641
                        mask = 511;
 
1642
                        break;
 
1643
        }
 
1644
 
 
1645
        /* Now we must calculate the offset q from the beginning of
 
1646
         * the buffer of the first line to print in this pass, and
 
1647
         * the total number of lines to be printed. We print as many
 
1648
         * lines as we can in a single pass, i.e. the value of "lines"
 
1649
         * is simply the number of lines that at the current vertical
 
1650
         * resolution fully cover the printing pen.
 
1651
         * Note that in case of monochrome printing we print all
 
1652
         * buffer lines, from first to last, so we also need to set
 
1653
         * the mask to a neutral value because we don't use wrapping.
 
1654
         */
 
1655
        if(gendata.rendermode == LXM3200_M)
 
1656
        {
 
1657
                mask = 511;
 
1658
                q = 0;
 
1659
                lines = gendata.numblines;
 
1660
        }
 
1661
        else
 
1662
        {
 
1663
                q = gendata.firstline + valign[BLACKVALIGN];
 
1664
                lines = (BWCOLPEN * 2) / gendata.yrmul;
 
1665
        }
 
1666
 
 
1667
        /* Adjust the value of the nozzle column separation to the
 
1668
         * horizontal resolution we are using now.
 
1669
         */
 
1670
        csep = (gendata.bwsep * 2) / gendata.xrmul;
 
1671
 
 
1672
        /* Here we calculate how many "real" passes we are doing.
 
1673
         * A "real" pass is a pass where a full column is printed
 
1674
         * and then some columns (maybe zero) are skipped before
 
1675
         * printing another one. If we are at 1200 dpi horizontal
 
1676
         * then we must use only one nozzle column at a time, so each
 
1677
         * real pass comprises two subpasses, one where we print with
 
1678
         * even nozzles only and another where we print with odd
 
1679
         * nozzles only. So at 1200 dpi the "real" passes are half the
 
1680
         * total number of passes. Another way of looking at it: the
 
1681
         * "nxp" variable holds the separation, in columns, between two
 
1682
         * dot columns printed in the same head sweep.
 
1683
         */
 
1684
        nxp = gendata.numpasses;
 
1685
        if(gendata.xres == 1200)nxp /= 2;
 
1686
 
 
1687
        /* Now calculate the byte increments for the *output* data
 
1688
         * buffer (i.e. the encoded buffer). The first variable,
 
1689
         * dy, is the number of bytes taken by a single data burst
 
1690
         * (both even and odd nozzle columns). The second variable,
 
1691
         * dy2, tells how many bytes we must skip from one column
 
1692
         * to the other (if we are printing multipass we skip some
 
1693
         * columns that will be printed in subsequent passes).
 
1694
         */
 
1695
        dy = (gendata.numlines / 8) + 4;
 
1696
        dy2 = dy * nxp;
 
1697
 
 
1698
        /* Calculate the starting and ending horizontal positions for
 
1699
         * this head pass. There are the margins corrected to take
 
1700
         * into account the displacement between the odd and even
 
1701
         * nozzle columns (csep). Moreover we start "csep" pixels
 
1702
         * before the margin to give the head a little more room to
 
1703
         * accelerate properly (not sure if this really works, but it
 
1704
         * doesn't cost much, so I've left it in).
 
1705
         */
 
1706
        if(gendata.direction == LEFT)
 
1707
        {
 
1708
                left = gendata.left - 2*csep;
 
1709
                right = gendata.right + csep;
 
1710
        }
 
1711
        else
 
1712
        {
 
1713
                left = gendata.left - csep;
 
1714
                right = gendata.right + 2*csep;
 
1715
        }
 
1716
 
 
1717
        /* Number of columns in a full row */
 
1718
        numcols = right - left;
 
1719
 
 
1720
        /* Calculate the last pixel of the first pass of the
 
1721
         * stripe. If we are printing bidirectionally, this
 
1722
         * will be the base to calculate the start of the
 
1723
         * passes printed right-to-left.
 
1724
         */
 
1725
        mod = numcols - (numcols % nxp);
 
1726
 
 
1727
        /* f1 and f2 are two flags that define which nozzle columns
 
1728
         * we are using in this stripe, f1 for the even nozzle column
 
1729
         * and f2 for the odd nozzle column: if they are zero that
 
1730
         * nozzle column is not used in this pass.
 
1731
         */
 
1732
        f1 = 1;
 
1733
        f2 = 1;
 
1734
        if(gendata.yres == 300)
 
1735
        {
 
1736
                /* At 300 dpi we use only one nozzle column. As of now this
 
1737
                 * is always the even one, but maybe it could be tried to
 
1738
                 * alternate between columns at each pass, to improve the
 
1739
                 * output quality.
 
1740
                 */
 
1741
                f1 = 1;
 
1742
                f2 = 0;
 
1743
        }
 
1744
 
 
1745
        /* Now start the passes to fill all the stripe */
 
1746
        for(pass = 0; pass < gendata.numpasses; pass++)
 
1747
        {
 
1748
                /* If there is data in the buffer which has not been
 
1749
                 * sent to the printer yet, send it now.
 
1750
                 */
 
1751
                if(gendata.fullflag)
 
1752
                {
 
1753
                        fwrite(gendata.header, 3, 8, gendata.stream);
 
1754
                        fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
 
1755
                        gendata.fullflag = FALSE;
 
1756
                }
 
1757
 
 
1758
                /* Clear the output buffer to avoid problems with the bitwise
 
1759
                 * operations we will do later on.
 
1760
                 */
 
1761
                memset(gendata.outdata, 0, gendata.numbytes * 30);
 
1762
 
 
1763
                /* Calculate standard increments, starting column
 
1764
                 * and start of output data. They will be corrected
 
1765
                 * later for 1200dpi or right-to-left printing direction.
 
1766
                 */
 
1767
                incr = nxp;
 
1768
                start = left + pass;
 
1769
                data = gendata.outdata + (pass*dy) + 4;
 
1770
 
 
1771
                /* It appears that at 1200dpi, in addition of not being able
 
1772
                 * to use 208 nozzles mode for the black cartridge, the Lexmark
 
1773
                 * 3200 cannot print at full rate with all the 192 useable nozzles.
 
1774
                 * Maybe the reason is that the data rate of 1200dpi horizontal
 
1775
                 * resolution exceeds the mechanical/thermal limits of the heads.
 
1776
                 * So if we are printing at 1200dpi we need to use alternatively
 
1777
                 * only odd or even numbered nozzles, for each printed column, to
 
1778
                 * half the data rate towards the head.
 
1779
                 * This obviously means that, at 1200dpi horizontal, a minimum of
 
1780
                 * two passes are required to print each stripe. Since if we are
 
1781
                 * printing at 1200dpi vertical we need two interlaced passes, a
 
1782
                 * minimum grand total of 4 passes are needed to print one full
 
1783
                 * 1200x1200 dpi stripe with the Lexmark 3200.
 
1784
                 */
 
1785
                if(gendata.xres == 1200)
 
1786
                {
 
1787
                        f1 = pass & 1;
 
1788
                        f2 = 1 - f1;
 
1789
 
 
1790
                        start = left + (pass/2);
 
1791
                        data = gendata.outdata + ((pass/2)*dy) + 4;
 
1792
                }
 
1793
 
 
1794
                /* If printing right-to-left we need to present data
 
1795
                 * to the printer in that direction, inverting the
 
1796
                 * normal flow of data.
 
1797
                 */
 
1798
                if(gendata.direction == RIGHT)
 
1799
                {
 
1800
                        incr = -nxp;
 
1801
                        start += mod;
 
1802
                }
 
1803
 
 
1804
                /* Start column scanning */
 
1805
                x = start;
 
1806
 
 
1807
                /* Now we split the behaviour depending on the printing
 
1808
                 * direction. To be honest, the inner loops are almost
 
1809
                 * identical between left-to-right and right-to-left
 
1810
                 * directions. The only difference is where is computed
 
1811
                 * the contribute of the nozzle columns separation ("csep"),
 
1812
                 * but having the "if" outside the loop it's somehow better.
 
1813
                 */
 
1814
                if(gendata.direction == LEFT)
 
1815
                {
 
1816
                        /* For all the columns in this pass */
 
1817
                        for(nn = 0; nn < numcols; nn += nxp)
 
1818
                        {
 
1819
                                /* Encode the even numbered nozzles */
 
1820
                                if((x >= 0) && f1)
 
1821
                                {
 
1822
                                        scan = gendata.scanbuf + x;
 
1823
                                        yy = 0;
 
1824
                                        for(y = s1; y < lines; y += yincr)
 
1825
                                        {
 
1826
                                                if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
 
1827
                                                        data[yy/8] |= bits[yy&7];
 
1828
                                                yy += 2;
 
1829
                                        }
 
1830
                                }
 
1831
 
 
1832
                                /* Encode the odd numbered nozzles */
 
1833
                                if(((x+csep) < gendata.numbytes) && f2)
 
1834
                                {
 
1835
                                        scan = gendata.scanbuf + x + csep;
 
1836
                                        yy = 1;
 
1837
                                        for(y = s2; y < lines; y += yincr)
 
1838
                                        {
 
1839
                                                if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
 
1840
                                                        data[yy/8] |= bits[yy&7];
 
1841
                                                yy += 2;
 
1842
                                        }
 
1843
                                }
 
1844
 
 
1845
                                /* If we are in 1200dpi horizontal resolution,
 
1846
                                 * alternate between nozzle columns to avoid
 
1847
                                 * overstressing the printing head.
 
1848
                                 */
 
1849
                                if(gendata.xres == 1200)
 
1850
                                {
 
1851
                                        f1 = 1 - f1;
 
1852
                                        f2 = 1 - f2;
 
1853
                                }
 
1854
 
 
1855
                                /* Adjust data pointers */
 
1856
                                data += dy2;
 
1857
                                x += incr;
 
1858
                        }
 
1859
                }
 
1860
                else /* direction == RIGHT */
 
1861
                {
 
1862
                        /* For all the columns in this pass */
 
1863
                        for(nn = 0; nn < numcols; nn += nxp)
 
1864
                        {
 
1865
                                /* Encode the odd numbered nozzles */
 
1866
                                if((x < gendata.numbytes) && f1)
 
1867
                                {
 
1868
                                        scan = gendata.scanbuf + x;
 
1869
                                        yy = 1;
 
1870
                                        for(y = s1; y < lines; y += yincr)
 
1871
                                        {
 
1872
                                                if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
 
1873
                                                        data[yy/8] |= bits[yy&7];
 
1874
                                                yy += 2;
 
1875
                                        }
 
1876
                                }
 
1877
 
 
1878
                                /* Encode the even numbered nozzles */
 
1879
                                if(((x-csep) >= 0) && f2)
 
1880
                                {
 
1881
                                        scan = gendata.scanbuf + x - csep;
 
1882
                                        yy = 0;
 
1883
                                        for(y = s2; y < lines; y += yincr)
 
1884
                                        {
 
1885
                                                if(scan[((y+q) & mask)*gendata.numbytes] & BLACK)
 
1886
                                                        data[yy/8] |= bits[yy&7];
 
1887
                                                yy += 2;
 
1888
                                        }
 
1889
                                }
 
1890
 
 
1891
                                /* If we are in 1200dpi horizontal resolution,
 
1892
                                 * alternate between nozzle columns to avoid
 
1893
                                 * overstressing the printing head.
 
1894
                                 */
 
1895
                                if(gendata.xres == 1200)
 
1896
                                {
 
1897
                                        f1 = 1 - f1;
 
1898
                                        f2 = 1 - f2;
 
1899
                                }
 
1900
 
 
1901
                                /* Adjust data pointers */
 
1902
                                data += dy2;
 
1903
                                x += incr;
 
1904
                        }
 
1905
                }
 
1906
 
 
1907
                /* Convert the buffer to the shortest output format.
 
1908
                 * Which is the first column of the output depends
 
1909
                 * on the printing direction: it will be the left
 
1910
                 * margin if we are printing left to right or the
 
1911
                 * right margin if we are printing right to left.
 
1912
                 */
 
1913
                if(gendata.direction == LEFT)
 
1914
                        convbuf(LEFT, numcols, left);
 
1915
                else
 
1916
                        convbuf(LEFT, numcols, right);
 
1917
        }
1921
1918
}
1922
1919
 
1923
1920
/* This routine is the equivalent of encode_bw_buf() but
1924
1921
 * for color or photo cartridge. Since this routine is
1925
1922
 * heavily based on the B/W one, the comments here will
1926
 
 * be somewhat less esaurient. Please have a look at 
 
1923
 * be somewhat less esaurient. Please have a look at
1927
1924
 * encode_bw_buf() to understand better how this routine
1928
1925
 * works: I will only pinpoint the differences between this
1929
1926
 * routine and encode_bw_buf().
1931
1928
 * head: the head we are calculating the buffer for. It will
1932
1929
 *       be LEFT for a photo cartridge or RIGHT for a color one.
1933
1930
 */
1934
 
static void 
 
1931
static void
1935
1932
encode_col_buf(int head)
1936
1933
{
1937
 
        int left, right, x, y, nn, mod;
1938
 
        int nxp, yy, numcols, incr;
1939
 
        int dy, dy2, csep, pass, f1;
1940
 
        int f2, start, s1, s2, yincr;
1941
 
        int q, mask, k, align, lines;
1942
 
        byte *scan, *data;
1943
 
 
1944
 
        /* Here there are two more parameters: mask and lines, that
1945
 
         * for color cartridges are both dependent on vertical
1946
 
         * resolution. Since the buffer is "rolling", i.e. it is
1947
 
         * implemented as a circular array, all the coordinates of
1948
 
         * the buffer lines must be taken modulo the buffer length.
1949
 
         * We choose a buffer length that is a power of two to be
1950
 
         * able to turn the modulo operation into a bitwise AND, so
1951
 
         * we need to set "mask" to the correct value for the AND.
1952
 
         * Another difference is that "lines", i.e. the number of
1953
 
         * lines to print in each pass, is based on the height of a 
1954
 
         * color pen. Since there are three color pens in each cartridge,
1955
 
         * each color pen is treated separately to fully cover the
1956
 
         * printing head.
1957
 
         */
1958
 
        switch(gendata.yres)
1959
 
        {
1960
 
                case 300:
1961
 
                        yincr = 1;
1962
 
                        s1 = 0;
1963
 
                        s2 = 0;
1964
 
                        mask = 127;
1965
 
                        lines = COLORPEN/2;
1966
 
                        break;
1967
 
                        
1968
 
                default:
1969
 
                case 600:
1970
 
                        yincr = 2;
1971
 
                        s1 = 0;
1972
 
                        s2 = 1;
1973
 
                        mask = 255;
1974
 
                        lines = COLORPEN;
1975
 
                        break;
1976
 
                        
1977
 
                case 1200:
1978
 
                        yincr = 4;
1979
 
                        s1 = (gendata.ileave ? 1 : 0);
1980
 
                        s2 = (gendata.ileave ? 3 : 2);
1981
 
                        mask = 511;
1982
 
                        lines = COLORPEN*2;
1983
 
                        break;
1984
 
        }
1985
 
        
1986
 
        /* Choose the vertical alignment depending on the head.
1987
 
         * This is needed to vertically align the color cartridge 
1988
 
         * with the photo or black cartridge.
1989
 
         */
1990
 
        if(head == LEFT)
1991
 
                align = valign[PHOTOVALIGN];
1992
 
        else
1993
 
                align = valign[COLORVALIGN];            
1994
 
 
1995
 
        /* All the stuff below is exactly the same as in
1996
 
         * encode_bw_buf(), and is therefore commented there.
1997
 
         */
1998
 
 
1999
 
        csep = (gendata.bwsep * 2) / gendata.xrmul;
2000
 
        nxp = gendata.numpasses;
2001
 
        if(gendata.xres == 1200)nxp /= 2; 
2002
 
 
2003
 
        dy = (gendata.numlines / 8) + 4;
2004
 
        dy2 = dy * nxp;
2005
 
 
2006
 
        if(gendata.direction == LEFT)
2007
 
        {
2008
 
                left = gendata.left - 2*csep;
2009
 
                right = gendata.right + csep;
2010
 
        }
2011
 
        else
2012
 
        {
2013
 
                left = gendata.left - csep;
2014
 
                right = gendata.right + 2*csep;
2015
 
        }
2016
 
        
2017
 
        numcols = right - left;
2018
 
        mod = numcols - (numcols % nxp);
2019
 
        
2020
 
        f1 = 1;
2021
 
        f2 = 1;
2022
 
        if(gendata.yres == 300)
2023
 
        {
2024
 
                f1 = 1;
2025
 
                f2 = 0;
2026
 
        }
2027
 
 
2028
 
        /* For all passes */
2029
 
        for(pass = 0; pass < gendata.numpasses; pass++)
2030
 
        {
2031
 
                /* If there is data in the buffer which has not been
2032
 
                 * sent to the printer yet, do it now.
2033
 
                 */
2034
 
                if(gendata.fullflag)
2035
 
                {
2036
 
                        fwrite(gendata.header, 3, 8, gendata.stream);
2037
 
                        fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
2038
 
                        gendata.fullflag = FALSE;
2039
 
                }
2040
 
 
2041
 
                /* All the stuff below is exactly the same as in
2042
 
                 * encode_bw_buf(), and is therefore commented there.
2043
 
                 */
2044
 
 
2045
 
                memset(gendata.outdata, 0, gendata.numbytes * 30);
2046
 
                
2047
 
                incr = nxp;
2048
 
                start = left + pass;
2049
 
                data = gendata.outdata + (pass*dy) + 4;
2050
 
                
2051
 
                if(gendata.xres == 1200)
2052
 
                {
2053
 
                        f1 = pass & 1;
2054
 
                        f2 = 1 - f1;
2055
 
                        
2056
 
                        start = left + (pass/2);
2057
 
                        data = gendata.outdata + ((pass/2)*dy) + 4;
2058
 
                }
2059
 
                
2060
 
                if(gendata.direction == RIGHT)
2061
 
                {
2062
 
                        incr = -nxp;
2063
 
                        start += mod;
2064
 
                }
2065
 
                
2066
 
                /* Start column scanning */
2067
 
                x = start;
2068
 
 
2069
 
                if(gendata.direction == LEFT)
2070
 
                {
2071
 
                        /* For all the columns */
2072
 
                        for(nn = 0; nn < numcols; nn += nxp)
2073
 
                        {
2074
 
                                /* Encode the even numbered nozzles */
2075
 
                                if((x >= 0) && f1)
2076
 
                                {
2077
 
                                        scan = gendata.scanbuf + x;
2078
 
                                        yy = 0;
2079
 
 
2080
 
                                        /* In color printing there is one more loop to scan 
2081
 
                                         * all three color pens. We have to do exactly the 
2082
 
                                         * same things for all pens: the only differences are 
2083
 
                                         * the color encoding bit we are testing and the offset 
2084
 
                                         * from the beginning of the buffer and the offset of the 
2085
 
                                         * output data. All of this is stored into arrays. The 
2086
 
                                         * "penofs" array stores the offset of the first line of 
2087
 
                                         * each pen in the raster buffer. The array "colmask" stores
2088
 
                                         * the encoding bits for the color of each pen, and it
2089
 
                                         * is bidimensional because pen masks are different between
2090
 
                                         * a color cartridge (where pens are Cyan, Magenta, Yellow)
2091
 
                                         * and a photo cartridge (where pens are LightCyan, 
2092
 
                                         * LightMagenta and Black).
2093
 
                                         */
2094
 
                                        for(k=0; k<3; k++)
2095
 
                                        {
2096
 
                                                q = gendata.firstline + align + penofs[k];
2097
 
                                                for(y = s1; y < lines; y += yincr)
2098
 
                                                {
2099
 
                                                        if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2100
 
                                                                data[yy/8] |= bits[yy&7];
2101
 
                                                        yy += 2;
2102
 
                                                }
2103
 
                                        }
2104
 
                                }
2105
 
 
2106
 
                                /* Encode the odd numbered nozzles */ 
2107
 
                                if(((x+csep) < gendata.numbytes) && f2)
2108
 
                                {
2109
 
                                        scan = gendata.scanbuf + x + csep;
2110
 
                                        yy = 1;
2111
 
                                        for(k=0; k<3; k++)
2112
 
                                        {
2113
 
                                                q = gendata.firstline + align + penofs[k];
2114
 
                                                for(y = s2; y < lines; y += yincr)
2115
 
                                                {
2116
 
                                                        if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2117
 
                                                                data[yy/8] |= bits[yy&7];
2118
 
                                                        yy += 2;
2119
 
                                                }
2120
 
                                        }
2121
 
                                }
2122
 
 
2123
 
                                /* If we are in 1200dpi horizontal resolution,
2124
 
                                 * alternate between nozzle columns to avoid
2125
 
                                 * overstressing the printing head.
2126
 
                                 */
2127
 
                                if(gendata.xres == 1200)
2128
 
                                {
2129
 
                                        f1 = 1 - f1;
2130
 
                                        f2 = 1 - f2;
2131
 
                                }
2132
 
                                
2133
 
                                /* Adjust data pointers */
2134
 
                                data += dy2;
2135
 
                                x += incr;
2136
 
                        }
2137
 
                }                       
2138
 
                else
2139
 
                {
2140
 
                        /* For all the columns */
2141
 
                        for(nn = 0; nn < numcols; nn += nxp)
2142
 
                        {                       
2143
 
                                /* Encode the odd numbered nozzles */ 
2144
 
                                if((x < gendata.numbytes) && f1)
2145
 
                                {
2146
 
                                        scan = gendata.scanbuf + x;
2147
 
                                        yy = 1;
2148
 
                                        for(k=0; k<3; k++)
2149
 
                                        {
2150
 
                                                q = gendata.firstline + align + penofs[k];
2151
 
                                                for(y = s1; y < lines; y += yincr)
2152
 
                                                {
2153
 
                                                        if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2154
 
                                                                data[yy/8] |= bits[yy&7];
2155
 
                                                        yy += 2;
2156
 
                                                }
2157
 
                                        }
2158
 
                                }
2159
 
 
2160
 
                                /* Encode the even numbered nozzles */                          
2161
 
                                if(((x-csep) >= 0) && f2)
2162
 
                                {
2163
 
                                        scan = gendata.scanbuf + x - csep;
2164
 
                                        yy = 0;
2165
 
                                        for(k=0; k<3; k++)
2166
 
                                        {
2167
 
                                                q = gendata.firstline + align + penofs[k];
2168
 
                                                for(y = s2; y < lines; y += yincr)
2169
 
                                                {
2170
 
                                                        if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2171
 
                                                                data[yy/8] |= bits[yy&7];
2172
 
                                                        yy += 2;
2173
 
                                                }
2174
 
                                        }
2175
 
                                }
2176
 
 
2177
 
                                /* If we are in 1200dpi horizontal resolution,
2178
 
                                 * alternate between nozzle columns to avoid 
2179
 
                                 * overstressing the printing head.
2180
 
                                 */
2181
 
                                if(gendata.xres == 1200)
2182
 
                                {
2183
 
                                        f1 = 1 - f1;
2184
 
                                        f2 = 1 - f2;
2185
 
                                }
2186
 
                                
2187
 
                                /* Adjust data pointers */
2188
 
                                data += dy2;
2189
 
                                x += incr;
2190
 
                        }
2191
 
                }
2192
 
                
2193
 
                if(gendata.direction == LEFT)
2194
 
                        convbuf(head, numcols, left);
2195
 
                else
2196
 
                        convbuf(head, numcols, right);
2197
 
        }
 
1934
        int left, right, x, y, nn, mod;
 
1935
        int nxp, yy, numcols, incr;
 
1936
        int dy, dy2, csep, pass, f1;
 
1937
        int f2, start, s1, s2, yincr;
 
1938
        int q, mask, k, align, lines;
 
1939
        byte *scan, *data;
 
1940
 
 
1941
        /* Here there are two more parameters: mask and lines, that
 
1942
         * for color cartridges are both dependent on vertical
 
1943
         * resolution. Since the buffer is "rolling", i.e. it is
 
1944
         * implemented as a circular array, all the coordinates of
 
1945
         * the buffer lines must be taken modulo the buffer length.
 
1946
         * We choose a buffer length that is a power of two to be
 
1947
         * able to turn the modulo operation into a bitwise AND, so
 
1948
         * we need to set "mask" to the correct value for the AND.
 
1949
         * Another difference is that "lines", i.e. the number of
 
1950
         * lines to print in each pass, is based on the height of a
 
1951
         * color pen. Since there are three color pens in each cartridge,
 
1952
         * each color pen is treated separately to fully cover the
 
1953
         * printing head.
 
1954
         */
 
1955
        switch(gendata.yres)
 
1956
        {
 
1957
                case 300:
 
1958
                        yincr = 1;
 
1959
                        s1 = 0;
 
1960
                        s2 = 0;
 
1961
                        mask = 127;
 
1962
                        lines = COLORPEN/2;
 
1963
                        break;
 
1964
 
 
1965
                default:
 
1966
                case 600:
 
1967
                        yincr = 2;
 
1968
                        s1 = 0;
 
1969
                        s2 = 1;
 
1970
                        mask = 255;
 
1971
                        lines = COLORPEN;
 
1972
                        break;
 
1973
 
 
1974
                case 1200:
 
1975
                        yincr = 4;
 
1976
                        s1 = (gendata.ileave ? 1 : 0);
 
1977
                        s2 = (gendata.ileave ? 3 : 2);
 
1978
                        mask = 511;
 
1979
                        lines = COLORPEN*2;
 
1980
                        break;
 
1981
        }
 
1982
 
 
1983
        /* Choose the vertical alignment depending on the head.
 
1984
         * This is needed to vertically align the color cartridge
 
1985
         * with the photo or black cartridge.
 
1986
         */
 
1987
        if(head == LEFT)
 
1988
                align = valign[PHOTOVALIGN];
 
1989
        else
 
1990
                align = valign[COLORVALIGN];
 
1991
 
 
1992
        /* All the stuff below is exactly the same as in
 
1993
         * encode_bw_buf(), and is therefore commented there.
 
1994
         */
 
1995
 
 
1996
        csep = (gendata.bwsep * 2) / gendata.xrmul;
 
1997
        nxp = gendata.numpasses;
 
1998
        if(gendata.xres == 1200)nxp /= 2;
 
1999
 
 
2000
        dy = (gendata.numlines / 8) + 4;
 
2001
        dy2 = dy * nxp;
 
2002
 
 
2003
        if(gendata.direction == LEFT)
 
2004
        {
 
2005
                left = gendata.left - 2*csep;
 
2006
                right = gendata.right + csep;
 
2007
        }
 
2008
        else
 
2009
        {
 
2010
                left = gendata.left - csep;
 
2011
                right = gendata.right + 2*csep;
 
2012
        }
 
2013
 
 
2014
        numcols = right - left;
 
2015
        mod = numcols - (numcols % nxp);
 
2016
 
 
2017
        f1 = 1;
 
2018
        f2 = 1;
 
2019
        if(gendata.yres == 300)
 
2020
        {
 
2021
                f1 = 1;
 
2022
                f2 = 0;
 
2023
        }
 
2024
 
 
2025
        /* For all passes */
 
2026
        for(pass = 0; pass < gendata.numpasses; pass++)
 
2027
        {
 
2028
                /* If there is data in the buffer which has not been
 
2029
                 * sent to the printer yet, do it now.
 
2030
                 */
 
2031
                if(gendata.fullflag)
 
2032
                {
 
2033
                        fwrite(gendata.header, 3, 8, gendata.stream);
 
2034
                        fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
 
2035
                        gendata.fullflag = FALSE;
 
2036
                }
 
2037
 
 
2038
                /* All the stuff below is exactly the same as in
 
2039
                 * encode_bw_buf(), and is therefore commented there.
 
2040
                 */
 
2041
 
 
2042
                memset(gendata.outdata, 0, gendata.numbytes * 30);
 
2043
 
 
2044
                incr = nxp;
 
2045
                start = left + pass;
 
2046
                data = gendata.outdata + (pass*dy) + 4;
 
2047
 
 
2048
                if(gendata.xres == 1200)
 
2049
                {
 
2050
                        f1 = pass & 1;
 
2051
                        f2 = 1 - f1;
 
2052
 
 
2053
                        start = left + (pass/2);
 
2054
                        data = gendata.outdata + ((pass/2)*dy) + 4;
 
2055
                }
 
2056
 
 
2057
                if(gendata.direction == RIGHT)
 
2058
                {
 
2059
                        incr = -nxp;
 
2060
                        start += mod;
 
2061
                }
 
2062
 
 
2063
                /* Start column scanning */
 
2064
                x = start;
 
2065
 
 
2066
                if(gendata.direction == LEFT)
 
2067
                {
 
2068
                        /* For all the columns */
 
2069
                        for(nn = 0; nn < numcols; nn += nxp)
 
2070
                        {
 
2071
                                /* Encode the even numbered nozzles */
 
2072
                                if((x >= 0) && f1)
 
2073
                                {
 
2074
                                        scan = gendata.scanbuf + x;
 
2075
                                        yy = 0;
 
2076
 
 
2077
                                        /* In color printing there is one more loop to scan
 
2078
                                         * all three color pens. We have to do exactly the
 
2079
                                         * same things for all pens: the only differences are
 
2080
                                         * the color encoding bit we are testing and the offset
 
2081
                                         * from the beginning of the buffer and the offset of the
 
2082
                                         * output data. All of this is stored into arrays. The
 
2083
                                         * "penofs" array stores the offset of the first line of
 
2084
                                         * each pen in the raster buffer. The array "colmask" stores
 
2085
                                         * the encoding bits for the color of each pen, and it
 
2086
                                         * is bidimensional because pen masks are different between
 
2087
                                         * a color cartridge (where pens are Cyan, Magenta, Yellow)
 
2088
                                         * and a photo cartridge (where pens are LightCyan,
 
2089
                                         * LightMagenta and Black).
 
2090
                                         */
 
2091
                                        for(k=0; k<3; k++)
 
2092
                                        {
 
2093
                                                q = gendata.firstline + align + penofs[k];
 
2094
                                                for(y = s1; y < lines; y += yincr)
 
2095
                                                {
 
2096
                                                        if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
 
2097
                                                                data[yy/8] |= bits[yy&7];
 
2098
                                                        yy += 2;
 
2099
                                                }
 
2100
                                        }
 
2101
                                }
 
2102
 
 
2103
                                /* Encode the odd numbered nozzles */
 
2104
                                if(((x+csep) < gendata.numbytes) && f2)
 
2105
                                {
 
2106
                                        scan = gendata.scanbuf + x + csep;
 
2107
                                        yy = 1;
 
2108
                                        for(k=0; k<3; k++)
 
2109
                                        {
 
2110
                                                q = gendata.firstline + align + penofs[k];
 
2111
                                                for(y = s2; y < lines; y += yincr)
 
2112
                                                {
 
2113
                                                        if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
 
2114
                                                                data[yy/8] |= bits[yy&7];
 
2115
                                                        yy += 2;
 
2116
                                                }
 
2117
                                        }
 
2118
                                }
 
2119
 
 
2120
                                /* If we are in 1200dpi horizontal resolution,
 
2121
                                 * alternate between nozzle columns to avoid
 
2122
                                 * overstressing the printing head.
 
2123
                                 */
 
2124
                                if(gendata.xres == 1200)
 
2125
                                {
 
2126
                                        f1 = 1 - f1;
 
2127
                                        f2 = 1 - f2;
 
2128
                                }
 
2129
 
 
2130
                                /* Adjust data pointers */
 
2131
                                data += dy2;
 
2132
                                x += incr;
 
2133
                        }
 
2134
                }
 
2135
                else
 
2136
                {
 
2137
                        /* For all the columns */
 
2138
                        for(nn = 0; nn < numcols; nn += nxp)
 
2139
                        {
 
2140
                                /* Encode the odd numbered nozzles */
 
2141
                                if((x < gendata.numbytes) && f1)
 
2142
                                {
 
2143
                                        scan = gendata.scanbuf + x;
 
2144
                                        yy = 1;
 
2145
                                        for(k=0; k<3; k++)
 
2146
                                        {
 
2147
                                                q = gendata.firstline + align + penofs[k];
 
2148
                                                for(y = s1; y < lines; y += yincr)
 
2149
                                                {
 
2150
                                                        if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
 
2151
                                                                data[yy/8] |= bits[yy&7];
 
2152
                                                        yy += 2;
 
2153
                                                }
 
2154
                                        }
 
2155
                                }
 
2156
 
 
2157
                                /* Encode the even numbered nozzles */
 
2158
                                if(((x-csep) >= 0) && f2)
 
2159
                                {
 
2160
                                        scan = gendata.scanbuf + x - csep;
 
2161
                                        yy = 0;
 
2162
                                        for(k=0; k<3; k++)
 
2163
                                        {
 
2164
                                                q = gendata.firstline + align + penofs[k];
 
2165
                                                for(y = s2; y < lines; y += yincr)
 
2166
                                                {
 
2167
                                                        if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
 
2168
                                                                data[yy/8] |= bits[yy&7];
 
2169
                                                        yy += 2;
 
2170
                                                }
 
2171
                                        }
 
2172
                                }
 
2173
 
 
2174
                                /* If we are in 1200dpi horizontal resolution,
 
2175
                                 * alternate between nozzle columns to avoid
 
2176
                                 * overstressing the printing head.
 
2177
                                 */
 
2178
                                if(gendata.xres == 1200)
 
2179
                                {
 
2180
                                        f1 = 1 - f1;
 
2181
                                        f2 = 1 - f2;
 
2182
                                }
 
2183
 
 
2184
                                /* Adjust data pointers */
 
2185
                                data += dy2;
 
2186
                                x += incr;
 
2187
                        }
 
2188
                }
 
2189
 
 
2190
                if(gendata.direction == LEFT)
 
2191
                        convbuf(head, numcols, left);
 
2192
                else
 
2193
                        convbuf(head, numcols, right);
 
2194
        }
2198
2195
}
2199
2196
 
2200
 
/* Fill monochrome buffer: this routine fills the buffer 
2201
 
 * with rasterized lines, skipping over vertical spacing 
2202
 
 * (i.e. completely blank lines). The routine is only 
2203
 
 * used in monochrome mode, where we print a full buffer 
2204
 
 * at each stripe. The color printing needs a different 
 
2197
/* Fill monochrome buffer: this routine fills the buffer
 
2198
 * with rasterized lines, skipping over vertical spacing
 
2199
 * (i.e. completely blank lines). The routine is only
 
2200
 * used in monochrome mode, where we print a full buffer
 
2201
 * at each stripe. The color printing needs a different
2205
2202
 * routine which makes use of a circular buffer.
2206
 
 * 
 
2203
 *
2207
2204
 * vline: the line from which to start searching for data.
2208
2205
 */
2209
2206
static int
2210
2207
fill_mono_buffer(int vline)
2211
2208
{
2212
 
        byte *in_data, *data;
2213
 
        int i, ret, ofs;
2214
 
 
2215
 
        /* Initialize the "data" pointer, that will be used to
2216
 
         * scan all the lines in the buffer, and the "ofs" pointer 
2217
 
         * that will be used to mark the start of the "real" rasterized 
2218
 
         * data into the buffer (see below). To compensate for the offsets 
2219
 
         * caused by the horizontal spacing between nozzle columns on a 
2220
 
         * cartridge, the head must start before the horizontal margin, so 
2221
 
         * the buffer width is slightly bigger than the width of the
2222
 
         * rasterized lines. The difference is the "guard offset", and the 
2223
 
         * variables gendata.numbytes and gendata.numrbytes hold respectively 
2224
 
         * the number of bytes in a buffer line and the number of bytes in a 
2225
 
         * rasterized scanline, while gendata.goffset contains the number of
2226
 
         * bytes reserved to the guard offset on each side of the scanline.
2227
 
         */
2228
 
        data = gendata.scanbuf;
2229
 
        ofs = gendata.goffset;
2230
 
 
2231
 
        /* Cycle until we have no more lines on the page */
2232
 
        while(vline < gendata.numvlines)
2233
 
        {
2234
 
                /* Ask Ghostscript for one rasterized line */
2235
 
                gdev_prn_get_bits((gx_device_printer *)gendata.dev,
2236
 
                                                                                        vline, data+ofs, &in_data);
2237
 
 
2238
 
                /* And check if it's all zero: if not, break out of
2239
 
                 * the loop. This nice trick with memcpy it's by Stephen
2240
 
                 * Taylor (if I'm not wrong...)
2241
 
 
2242
 
                 */
2243
 
                if(in_data[0] != 0 || 
2244
 
                         memcmp(in_data, in_data+1,gendata.numrbytes-1))break;
2245
 
                vline++;
2246
 
        }
2247
 
        
2248
 
        /* If we are here because no non-empty lines were found before 
2249
 
         * the end of the page, our work is over. Return to the caller 
2250
 
         * saying that this is the last buffer (LAST bit set) and it's 
2251
 
         * empty (no LHDATA or RHDATA bit set).
2252
 
         */
2253
 
        if(vline >= gendata.numvlines)return(LAST);
2254
 
        
2255
 
        /* This buffer contains at least one non-empty line.
2256
 
         * Adjust the current vertical position and load the first
2257
 
         * line into the buffer.
2258
 
         */
2259
 
        gendata.curvline = vline;
2260
 
        memset(data, 0, gendata.numbytes);
2261
 
        if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2262
 
        
2263
 
        vline++;
2264
 
        data += gendata.numbytes;
2265
 
        
2266
 
        /* Now initialize the return value to LHDATA (since at least
2267
 
         * one non-blank line was found, this buffer contains data, and
2268
 
         * it is obviously left-head data because we are in monochromatic 
2269
 
         * mode and so we are printing with left head only).
2270
 
         * After that, get as many rasterized lines as needed to fill the
2271
 
         * buffer, checking if in the process we have reached the end of 
2272
 
         * the page.
2273
 
         */
2274
 
        ret = LHDATA;
2275
 
        for(i=1; i<gendata.numblines; i++)
2276
 
        {
2277
 
                memset(data, 0, gendata.numbytes);
2278
 
                if(vline > gendata.numvlines)
2279
 
                {
2280
 
                        /* Ok, we are at the end of the page, so set the LAST bit
2281
 
                         * in the return value but don't exit the loop because we
2282
 
                         * need to make sure all remaining lines in the buffer will
2283
 
                         * be blanked (exiting now would leave them untouched from
2284
 
                         * the previous stripe). This is needed to avoid printing
2285
 
                         * random data under the bottom margin.
2286
 
                         */
2287
 
                        ret = LHDATA | LAST;
2288
 
                }
2289
 
                else
2290
 
                {
2291
 
                        /* If we are not at the end of the page, copy one more
2292
 
                         * scanline into the buffer.
2293
 
                         */
2294
 
                        gdev_prn_get_bits((gx_device_printer *)gendata.dev,
2295
 
                                                                                                vline, data+ofs, &in_data);       
2296
 
                        if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2297
 
                }
2298
 
 
2299
 
                vline++;
2300
 
                data += gendata.numbytes;
2301
 
 
2302
 
        }
2303
 
        
2304
 
        return(ret);
 
2209
        byte *in_data, *data;
 
2210
        int i, ret, ofs;
 
2211
 
 
2212
        /* Initialize the "data" pointer, that will be used to
 
2213
         * scan all the lines in the buffer, and the "ofs" pointer
 
2214
         * that will be used to mark the start of the "real" rasterized
 
2215
         * data into the buffer (see below). To compensate for the offsets
 
2216
         * caused by the horizontal spacing between nozzle columns on a
 
2217
         * cartridge, the head must start before the horizontal margin, so
 
2218
         * the buffer width is slightly bigger than the width of the
 
2219
         * rasterized lines. The difference is the "guard offset", and the
 
2220
         * variables gendata.numbytes and gendata.numrbytes hold respectively
 
2221
         * the number of bytes in a buffer line and the number of bytes in a
 
2222
         * rasterized scanline, while gendata.goffset contains the number of
 
2223
         * bytes reserved to the guard offset on each side of the scanline.
 
2224
         */
 
2225
        data = gendata.scanbuf;
 
2226
        ofs = gendata.goffset;
 
2227
 
 
2228
        /* Cycle until we have no more lines on the page */
 
2229
        while(vline < gendata.numvlines)
 
2230
        {
 
2231
                /* Ask Ghostscript for one rasterized line */
 
2232
                gdev_prn_get_bits((gx_device_printer *)gendata.dev,
 
2233
                                                                                        vline, data+ofs, &in_data);
 
2234
 
 
2235
                /* And check if it's all zero: if not, break out of
 
2236
                 * the loop. This nice trick with memcpy it's by Stephen
 
2237
                 * Taylor (if I'm not wrong...)
 
2238
 
 
2239
                 */
 
2240
                if(in_data[0] != 0 ||
 
2241
                         memcmp(in_data, in_data+1,gendata.numrbytes-1))break;
 
2242
                vline++;
 
2243
        }
 
2244
 
 
2245
        /* If we are here because no non-empty lines were found before
 
2246
         * the end of the page, our work is over. Return to the caller
 
2247
         * saying that this is the last buffer (LAST bit set) and it's
 
2248
         * empty (no LHDATA or RHDATA bit set).
 
2249
         */
 
2250
        if(vline >= gendata.numvlines)return(LAST);
 
2251
 
 
2252
        /* This buffer contains at least one non-empty line.
 
2253
         * Adjust the current vertical position and load the first
 
2254
         * line into the buffer.
 
2255
         */
 
2256
        gendata.curvline = vline;
 
2257
        memset(data, 0, gendata.numbytes);
 
2258
        if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
 
2259
 
 
2260
        vline++;
 
2261
        data += gendata.numbytes;
 
2262
 
 
2263
        /* Now initialize the return value to LHDATA (since at least
 
2264
         * one non-blank line was found, this buffer contains data, and
 
2265
         * it is obviously left-head data because we are in monochromatic
 
2266
         * mode and so we are printing with left head only).
 
2267
         * After that, get as many rasterized lines as needed to fill the
 
2268
         * buffer, checking if in the process we have reached the end of
 
2269
         * the page.
 
2270
         */
 
2271
        ret = LHDATA;
 
2272
        for(i=1; i<gendata.numblines; i++)
 
2273
        {
 
2274
                memset(data, 0, gendata.numbytes);
 
2275
                if(vline > gendata.numvlines)
 
2276
                {
 
2277
                        /* Ok, we are at the end of the page, so set the LAST bit
 
2278
                         * in the return value but don't exit the loop because we
 
2279
                         * need to make sure all remaining lines in the buffer will
 
2280
                         * be blanked (exiting now would leave them untouched from
 
2281
                         * the previous stripe). This is needed to avoid printing
 
2282
                         * random data under the bottom margin.
 
2283
                         */
 
2284
                        ret = LHDATA | LAST;
 
2285
                }
 
2286
                else
 
2287
                {
 
2288
                        /* If we are not at the end of the page, copy one more
 
2289
                         * scanline into the buffer.
 
2290
                         */
 
2291
                        gdev_prn_get_bits((gx_device_printer *)gendata.dev,
 
2292
                                                                                                vline, data+ofs, &in_data);
 
2293
                        if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
 
2294
                }
 
2295
 
 
2296
                vline++;
 
2297
                data += gendata.numbytes;
 
2298
 
 
2299
        }
 
2300
 
 
2301
        return(ret);
2305
2302
}
2306
2303
 
2307
2304
/* Fill the buffer with initial data.
2310
2307
 * mode, we just call fill_mono_buffer for the first line.
2311
2308
 * If we are printing in color mode, we have a problem to
2312
2309
 * solve: since the color pen are stacked vertically, we
2313
 
 * need multiple head passes to print all colors on the 
 
2310
 * need multiple head passes to print all colors on the
2314
2311
 * same line. So, to simplify all, we start with the paper
2315
2312
 * at a fixed vertical position, even if it's blank, and
2316
2313
 * then we go down in fixed increments, equal to the height
2317
2314
 * of a color pen. This means we check all buffers without
2318
2315
 * skipping over blank ones, but since we actually send the
2319
2316
 * printing commands to the printer only when there is something
2320
 
 * to print, there is no speed impact. 
 
2317
 * to print, there is no speed impact.
2321
2318
 */
2322
 
static int 
 
2319
static int
2323
2320
init_buffer(void)
2324
2321
{
2325
 
        byte *in_data, *data;
2326
 
        int i, ret, p1, p2, ofs;
2327
 
 
2328
 
        data = gendata.scanbuf;
2329
 
        ofs = gendata.goffset;
2330
 
 
2331
 
        if(gendata.rendermode == LXM3200_M)return(fill_mono_buffer(0));
2332
 
 
2333
 
        /* We position the heads with the bottom color pen (the
2334
 
         * yellow one in the color cartridge and the black one
2335
 
         * in the photo cartridge) just covering the first lines
2336
 
         * of the paper sheet. So the first buffer is divided in
2337
 
         * two parts: "p1" is the number of lines above the top
2338
 
         * border and "p2" the number of lines below.
2339
 
         */
2340
 
        p1 = 368 / gendata.yrmul;
2341
 
        p2 = 144 / gendata.yrmul;
2342
 
 
2343
 
        /* Initialize the counters */
2344
 
        gendata.curvline = -p1;
2345
 
        gendata.lastblack = gendata.curvline - 1;
2346
 
        data = gendata.scanbuf;
2347
 
 
2348
 
        /* Clear the lines of the buffer that correspond to
2349
 
         * lines above the top margin: of course we don't
2350
 
         * want to print anything on the air... 
2351
 
         */
2352
 
        for(i=0; i<p1; i++)
2353
 
        {
2354
 
                memset(data, 0, gendata.numbytes);
2355
 
                data += gendata.numbytes;
2356
 
        }
2357
 
 
2358
 
        /* And now load the last part of the buffer.
2359
 
         * Note that here we don't check for blank lines,
2360
 
         * this will be cared for later.
2361
 
         */
2362
 
        for(i=0; i<p2; i++)
2363
 
        {
2364
 
                memset(data, 0, gendata.numbytes);
2365
 
 
2366
 
                if(i < gendata.numvlines)
2367
 
                {
2368
 
                        gdev_prn_get_bits((gx_device_printer *)gendata.dev,
2369
 
                                                                                                i, data+ofs, &in_data);                                 
2370
 
                        if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2371
 
                }
2372
 
 
2373
 
                data += gendata.numbytes;
2374
 
        }
2375
 
 
2376
 
        gendata.firstline = 0;
2377
 
 
2378
 
        /* Now check the return value. If by chance we are under
2379
 
         * the bottom margin, add the LAST bit to the return value.
2380
 
         * Of course, since this is the first buffer of the page,
2381
 
         * it's not likely we will reach the bottom margin in 
2382
 
         * this pass. Anyway this is code that will be executed
2383
 
         * only once per page, so better safe than sorry.
2384
 
         */
2385
 
        ret = (gendata.numvlines < p2 ? LAST : 0) | qualify_buffer();
2386
 
 
2387
 
        return(ret);
 
2322
        byte *in_data, *data;
 
2323
        int i, ret, p1, p2, ofs;
 
2324
 
 
2325
        data = gendata.scanbuf;
 
2326
        ofs = gendata.goffset;
 
2327
 
 
2328
        if(gendata.rendermode == LXM3200_M)return(fill_mono_buffer(0));
 
2329
 
 
2330
        /* We position the heads with the bottom color pen (the
 
2331
         * yellow one in the color cartridge and the black one
 
2332
         * in the photo cartridge) just covering the first lines
 
2333
         * of the paper sheet. So the first buffer is divided in
 
2334
         * two parts: "p1" is the number of lines above the top
 
2335
         * border and "p2" the number of lines below.
 
2336
         */
 
2337
        p1 = 368 / gendata.yrmul;
 
2338
        p2 = 144 / gendata.yrmul;
 
2339
 
 
2340
        /* Initialize the counters */
 
2341
        gendata.curvline = -p1;
 
2342
        gendata.lastblack = gendata.curvline - 1;
 
2343
        data = gendata.scanbuf;
 
2344
 
 
2345
        /* Clear the lines of the buffer that correspond to
 
2346
         * lines above the top margin: of course we don't
 
2347
         * want to print anything on the air...
 
2348
         */
 
2349
        for(i=0; i<p1; i++)
 
2350
        {
 
2351
                memset(data, 0, gendata.numbytes);
 
2352
                data += gendata.numbytes;
 
2353
        }
 
2354
 
 
2355
        /* And now load the last part of the buffer.
 
2356
         * Note that here we don't check for blank lines,
 
2357
         * this will be cared for later.
 
2358
         */
 
2359
        for(i=0; i<p2; i++)
 
2360
        {
 
2361
                memset(data, 0, gendata.numbytes);
 
2362
 
 
2363
                if(i < gendata.numvlines)
 
2364
                {
 
2365
                        gdev_prn_get_bits((gx_device_printer *)gendata.dev,
 
2366
                                                                                                i, data+ofs, &in_data);
 
2367
                        if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
 
2368
                }
 
2369
 
 
2370
                data += gendata.numbytes;
 
2371
        }
 
2372
 
 
2373
        gendata.firstline = 0;
 
2374
 
 
2375
        /* Now check the return value. If by chance we are under
 
2376
         * the bottom margin, add the LAST bit to the return value.
 
2377
         * Of course, since this is the first buffer of the page,
 
2378
         * it's not likely we will reach the bottom margin in
 
2379
         * this pass. Anyway this is code that will be executed
 
2380
         * only once per page, so better safe than sorry.
 
2381
         */
 
2382
        ret = (gendata.numvlines < p2 ? LAST : 0) | qualify_buffer();
 
2383
 
 
2384
        return(ret);
2388
2385
}
2389
2386
 
2390
2387
/* This function checks if the current buffer contains
2391
2388
 * data to be printed with the left or right head.
2392
2389
 * It assumes that we are printing in color mode, and it
2393
2390
 * is useful to minimize the number of needed passes.
2394
 
 * When we are printing in monochrome mode we directly skip 
 
2391
 * When we are printing in monochrome mode we directly skip
2395
2392
 * over blank lines, so this routine is not needed.
2396
2393
 */
2397
2394
static int
2398
2395
qualify_buffer(void)
2399
2396
{
2400
 
        int i, j, k, ret;
2401
 
        int rmsk, q, v1;
2402
 
        int bpsz, cpsz;
2403
 
        byte *data;
2404
 
 
2405
 
        ret = 0;
2406
 
 
2407
 
        /* Set variables which contains the size, in rows, of 
2408
 
         * each color pen and of the black pen in color mode,
2409
 
         * adjusting for different resolution settings.
2410
 
         * Also set the mask used to rollover the buffer.
2411
 
         */
2412
 
        cpsz = (COLORPEN * 2) / gendata.yrmul;
2413
 
        bpsz = (BWCOLPEN * 2) / gendata.yrmul;
2414
 
        rmsk = gendata.numblines - 1;
2415
 
 
2416
 
        /* Check the right head data, it is always a color cartridge */
2417
 
        for(k=0; k<3 && ret==0; k++)
2418
 
        {
2419
 
                /* For each pen, scan all the bytes on each row of 
2420
 
                 * the buffer that is covered by the current pen,
2421
 
                 * ORing together all the bits.
2422
 
                 */
2423
 
                v1 = 0;
2424
 
                q = gendata.firstline + valign[COLORVALIGN] + penofs[k];
2425
 
                for(i=0; i<cpsz; i++)
2426
 
                {
2427
 
                        data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
2428
 
                        for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
2429
 
                }
2430
 
                /* If the result of the OR has the proper color bit
2431
 
                 * set, it means that this buffer contains at least
2432
 
                 * one pixel of this pen, so we need a color pass.
2433
 
                 * Note that we exit as soon as we find a color bit
2434
 
                 * set, because if at least one color pen is used
2435
 
                 * in this buffer we need to do a color pass anyway,
2436
 
                 * so there's no need to check the other two pens.
2437
 
                 */
2438
 
                if(v1 & colmask[RIGHT][k])ret |= RHDATA;
2439
 
        }
2440
 
 
2441
 
        /* Check the left head data: it could be a black or
2442
 
         * a photo cartridge, depending on the printing mode.
2443
 
         */
2444
 
        if(gendata.rendermode == LXM3200_C)
2445
 
        {       
2446
 
                /* We are in standard color mode: the left cartridge 
2447
 
                 * is a black cartridge used in 192 nozzles mode.
2448
 
                 * This is done exactly in the same way as above, but
2449
 
                 * without the outer loop because we have only one
2450
 
                 * color pen on this cartridge.
2451
 
                 */
2452
 
                v1 = 0;
2453
 
                q = gendata.firstline + valign[BLACKVALIGN]; 
2454
 
                for(i=0; i<bpsz; i++)
2455
 
                {
2456
 
                        data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
2457
 
                        for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
2458
 
                }
2459
 
                if(v1 & BLACK)ret |= LHDATA;
2460
 
        }
2461
 
        else
2462
 
        {
2463
 
                /* If we are here we need to check for a photo cartridge
2464
 
                 * (this routine is never called in monochrome mode, so
2465
 
                 * if we are not in color mode we must be in photo mode).
2466
 
                 * This routine is identical to the color routine above.
2467
 
                 */
2468
 
                for(k=0; k<3 && !(ret & LHDATA); k++)
2469
 
                {
2470
 
                        v1 = 0;
2471
 
                        q = gendata.firstline + valign[PHOTOVALIGN] + penofs[k];
2472
 
                        for(i=0; i<cpsz; i++)
2473
 
                        {
2474
 
                                data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
2475
 
                                for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
2476
 
                        }
2477
 
                        if(v1 & colmask[LEFT][k])ret |= LHDATA;
2478
 
                }
2479
 
        }
2480
 
        
2481
 
        return(ret);
 
2397
        int i, j, k, ret;
 
2398
        int rmsk, q, v1;
 
2399
        int bpsz, cpsz;
 
2400
        byte *data;
 
2401
 
 
2402
        ret = 0;
 
2403
 
 
2404
        /* Set variables which contains the size, in rows, of
 
2405
         * each color pen and of the black pen in color mode,
 
2406
         * adjusting for different resolution settings.
 
2407
         * Also set the mask used to rollover the buffer.
 
2408
         */
 
2409
        cpsz = (COLORPEN * 2) / gendata.yrmul;
 
2410
        bpsz = (BWCOLPEN * 2) / gendata.yrmul;
 
2411
        rmsk = gendata.numblines - 1;
 
2412
 
 
2413
        /* Check the right head data, it is always a color cartridge */
 
2414
        for(k=0; k<3 && ret==0; k++)
 
2415
        {
 
2416
                /* For each pen, scan all the bytes on each row of
 
2417
                 * the buffer that is covered by the current pen,
 
2418
                 * ORing together all the bits.
 
2419
                 */
 
2420
                v1 = 0;
 
2421
                q = gendata.firstline + valign[COLORVALIGN] + penofs[k];
 
2422
                for(i=0; i<cpsz; i++)
 
2423
                {
 
2424
                        data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
 
2425
                        for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
 
2426
                }
 
2427
                /* If the result of the OR has the proper color bit
 
2428
                 * set, it means that this buffer contains at least
 
2429
                 * one pixel of this pen, so we need a color pass.
 
2430
                 * Note that we exit as soon as we find a color bit
 
2431
                 * set, because if at least one color pen is used
 
2432
                 * in this buffer we need to do a color pass anyway,
 
2433
                 * so there's no need to check the other two pens.
 
2434
                 */
 
2435
                if(v1 & colmask[RIGHT][k])ret |= RHDATA;
 
2436
        }
 
2437
 
 
2438
        /* Check the left head data: it could be a black or
 
2439
         * a photo cartridge, depending on the printing mode.
 
2440
         */
 
2441
        if(gendata.rendermode == LXM3200_C)
 
2442
        {
 
2443
                /* We are in standard color mode: the left cartridge
 
2444
                 * is a black cartridge used in 192 nozzles mode.
 
2445
                 * This is done exactly in the same way as above, but
 
2446
                 * without the outer loop because we have only one
 
2447
                 * color pen on this cartridge.
 
2448
                 */
 
2449
                v1 = 0;
 
2450
                q = gendata.firstline + valign[BLACKVALIGN];
 
2451
                for(i=0; i<bpsz; i++)
 
2452
                {
 
2453
                        data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
 
2454
                        for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
 
2455
                }
 
2456
                if(v1 & BLACK)ret |= LHDATA;
 
2457
        }
 
2458
        else
 
2459
        {
 
2460
                /* If we are here we need to check for a photo cartridge
 
2461
                 * (this routine is never called in monochrome mode, so
 
2462
                 * if we are not in color mode we must be in photo mode).
 
2463
                 * This routine is identical to the color routine above.
 
2464
                 */
 
2465
                for(k=0; k<3 && !(ret & LHDATA); k++)
 
2466
                {
 
2467
                        v1 = 0;
 
2468
                        q = gendata.firstline + valign[PHOTOVALIGN] + penofs[k];
 
2469
                        for(i=0; i<cpsz; i++)
 
2470
                        {
 
2471
                                data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
 
2472
                                for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
 
2473
                        }
 
2474
                        if(v1 & colmask[LEFT][k])ret |= LHDATA;
 
2475
                }
 
2476
        }
 
2477
 
 
2478
        return(ret);
2482
2479
}
2483
2480
 
2484
2481
/* This functions rolls the circular buffer by the
2485
2482
 * number of lines of one color pen, reading new
2486
2483
 * lines to refill the buffer.
2487
 
 * In color mode we use a circular buffer because 
 
2484
 * In color mode we use a circular buffer because
2488
2485
 * we need to read the same lines more than once.
2489
2486
 * So when we are forwarding to the next pass we
2490
2487
 * simply read in the new lines and then update the
2500
2497
static int
2501
2498
roll_buffer(void)
2502
2499
{
2503
 
        int i, ret, fline, vl, ofs;
2504
 
        int cpen, cmask, lline;
2505
 
        byte *data, *in_data;
2506
 
 
2507
 
        /* Adjust the size of the color pen and the
2508
 
         * mask to take into account the current resolution
2509
 
         */
2510
 
        cpen = (COLORPEN * 2) / gendata.yrmul;
2511
 
        cmask = (gendata.numblines) - 1;
2512
 
 
2513
 
        /* Calculate the line number corresponding to 
2514
 
         * the last buffer we can print before being
2515
 
         * forced to eject the page. At 600dpi this
2516
 
         * has been experimentally determined to be
2517
 
         * 112 lines from the bottom of the page.
2518
 
         */
2519
 
        lline = gendata.numvlines - (224 / gendata.yrmul);
2520
 
 
2521
 
        /* Roll the buffer by advancing the first line
2522
 
         * pointer by the height of one color pen.
2523
 
         */
2524
 
        fline = gendata.firstline;
2525
 
        gendata.firstline = (fline + cpen) & cmask;
2526
 
 
2527
 
        /* Now calculate the pointer to the first "fresh"
2528
 
         * line on the page, i.e. the first line we must
2529
 
         * read into the buffer at this pass.
2530
 
         */
2531
 
        vl = gendata.curvline + cmask + 1;
2532
 
 
2533
 
        /* Take into account the guard offset */
2534
 
        ofs = gendata.goffset;
2535
 
 
2536
 
        /* Initialize the return value and update the
2537
 
         * current vertical position on the page, while
2538
 
         * checking if we have reached the last printable
2539
 
         * buffer.
2540
 
         */
2541
 
        ret = 0;
2542
 
        gendata.curvline += cpen;
2543
 
        if(gendata.curvline >= lline)ret = LAST;
2544
 
 
2545
 
        /* Now read "fresh" rasterized scanlines into the
2546
 
         * input buffer.
2547
 
         */ 
2548
 
        for(i=0; i<cpen; i++)
2549
 
        {
2550
 
                data = gendata.scanbuf + ((fline + i) & cmask) * gendata.numbytes;
2551
 
 
2552
 
                memset(data, 0, gendata.numbytes);              
2553
 
                if(vl < gendata.numvlines)
2554
 
                {
2555
 
                        gdev_prn_get_bits((gx_device_printer *)gendata.dev, 
2556
 
                                                                                                vl, data+ofs, &in_data);
2557
 
                        if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2558
 
                }
2559
 
                vl++;
2560
 
        }
2561
 
        
2562
 
        /* And test for the presence of actual data to print */
2563
 
        ret |= qualify_buffer();
2564
 
 
2565
 
        return(ret);
 
2500
        int i, ret, fline, vl, ofs;
 
2501
        int cpen, cmask, lline;
 
2502
        byte *data, *in_data;
 
2503
 
 
2504
        /* Adjust the size of the color pen and the
 
2505
         * mask to take into account the current resolution
 
2506
         */
 
2507
        cpen = (COLORPEN * 2) / gendata.yrmul;
 
2508
        cmask = (gendata.numblines) - 1;
 
2509
 
 
2510
        /* Calculate the line number corresponding to
 
2511
         * the last buffer we can print before being
 
2512
         * forced to eject the page. At 600dpi this
 
2513
         * has been experimentally determined to be
 
2514
         * 112 lines from the bottom of the page.
 
2515
         */
 
2516
        lline = gendata.numvlines - (224 / gendata.yrmul);
 
2517
 
 
2518
        /* Roll the buffer by advancing the first line
 
2519
         * pointer by the height of one color pen.
 
2520
         */
 
2521
        fline = gendata.firstline;
 
2522
        gendata.firstline = (fline + cpen) & cmask;
 
2523
 
 
2524
        /* Now calculate the pointer to the first "fresh"
 
2525
         * line on the page, i.e. the first line we must
 
2526
         * read into the buffer at this pass.
 
2527
         */
 
2528
        vl = gendata.curvline + cmask + 1;
 
2529
 
 
2530
        /* Take into account the guard offset */
 
2531
        ofs = gendata.goffset;
 
2532
 
 
2533
        /* Initialize the return value and update the
 
2534
         * current vertical position on the page, while
 
2535
         * checking if we have reached the last printable
 
2536
         * buffer.
 
2537
         */
 
2538
        ret = 0;
 
2539
        gendata.curvline += cpen;
 
2540
        if(gendata.curvline >= lline)ret = LAST;
 
2541
 
 
2542
        /* Now read "fresh" rasterized scanlines into the
 
2543
         * input buffer.
 
2544
         */
 
2545
        for(i=0; i<cpen; i++)
 
2546
        {
 
2547
                data = gendata.scanbuf + ((fline + i) & cmask) * gendata.numbytes;
 
2548
 
 
2549
                memset(data, 0, gendata.numbytes);
 
2550
                if(vl < gendata.numvlines)
 
2551
                {
 
2552
                        gdev_prn_get_bits((gx_device_printer *)gendata.dev,
 
2553
                                                                                                vl, data+ofs, &in_data);
 
2554
                        if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
 
2555
                }
 
2556
                vl++;
 
2557
        }
 
2558
 
 
2559
        /* And test for the presence of actual data to print */
 
2560
        ret |= qualify_buffer();
 
2561
 
 
2562
        return(ret);
2566
2563
}
2567
2564
 
2568
 
/* Calculate the margins of one line, i.e. the leftmost 
 
2565
/* Calculate the margins of one line, i.e. the leftmost
2569
2566
 * and the rightmost non-blank pixel on the line.
2570
2567
 *
2571
2568
 * data:  the pointer to the data for this line
2575
2572
 * left:  calculated left margin (output variable)
2576
2573
 * right: calculated right margin (output variable)
2577
2574
 */
2578
 
static void 
 
2575
static void
2579
2576
calclinemargins(byte *data, int mask, int *left, int *right)
2580
2577
{
2581
 
        int l,r,num;
2582
 
 
2583
 
        num = gendata.numbytes - 1;
2584
 
 
2585
 
        l = 0;
2586
 
        while((l <= num) && ((data[l] & mask) == 0))l++;
2587
 
        
2588
 
        r = num;
2589
 
        while((r >= 0) && ((data[r] & mask) == 0))r--;
2590
 
 
2591
 
        *left = l;
2592
 
        *right = r;
 
2578
        int l,r,num;
 
2579
 
 
2580
        num = gendata.numbytes - 1;
 
2581
 
 
2582
        l = 0;
 
2583
        while((l <= num) && ((data[l] & mask) == 0))l++;
 
2584
 
 
2585
        r = num;
 
2586
        while((r >= 0) && ((data[r] & mask) == 0))r--;
 
2587
 
 
2588
        *left = l;
 
2589
        *right = r;
2593
2590
}
2594
2591
 
2595
2592
/* Calculate the margins of the whole buffer. The
2596
2593
 * calculation accounts separately for the data to
2597
2594
 * be printed with the left or with the right head,
2598
 
 * so we can try to minimize the head movement even 
 
2595
 * so we can try to minimize the head movement even
2599
2596
 * on multiple passes.
2600
 
 * 
 
2597
 *
2601
2598
 * head: the code of the head we are calculating
2602
2599
 *       margins for (LEFT or RIGHT)
2603
2600
 */
2604
2601
static void
2605
2602
calcbufmargins(int head)
2606
2603
{
2607
 
        int i, l1, r1, q, k;
2608
 
        int mleft, mright, nl;
2609
 
        int cpen, cmask, al;
2610
 
        byte *scan;
2611
 
 
2612
 
        /* Adjust mask and pen height according to vertical resolution */
2613
 
        cpen = (COLORPEN * 2) / gendata.yrmul;
2614
 
        cmask = (gendata.numblines) - 1;
2615
 
 
2616
 
        /* Calculate margins for a color or photo cartridge */
2617
 
        if(head == RIGHT || (gendata.rendermode == LXM3200_P))
2618
 
        {                               
2619
 
                /* Get correct vertical aligment */
2620
 
                al = (head == LEFT ? PHOTOVALIGN : COLORVALIGN);
2621
 
 
2622
 
                q = gendata.firstline + valign[al];
2623
 
 
2624
 
                /* Calculate margins for first line, using those values
2625
 
                 * to initialize the max and min values.
2626
 
                 */
2627
 
                scan = gendata.scanbuf + ((q+penofs[0]) & cmask)*gendata.numbytes;
2628
 
                calclinemargins(scan, colmask[head][0], &mleft, &mright);
2629
 
 
2630
 
                /* And now scan all the remaining buffer. We scan according
2631
 
                 * to color pens, i.e. we calculate the margin on the rows
2632
 
                 * where magenta will be laid down taking into account magenta
2633
 
                 * pixels only, and this will be the magenta submargin. After 
2634
 
                 * having done that for cyan and yellow as well, we take as the 
2635
 
                 * global margin the smaller space that contains all the three 
2636
 
                 * submargins.
2637
 
                 */
2638
 
                for(k=0; k<3; k++)
2639
 
                {
2640
 
                        for(i=0; i<cpen; i++)
2641
 
                        {
2642
 
                                scan = gendata.scanbuf + ((q+i+penofs[k]) & cmask)*gendata.numbytes;
2643
 
                                calclinemargins(scan, colmask[head][k], &l1, &r1);
2644
 
                                mleft = min(mleft, l1);
2645
 
                                mright = max(mright, r1);
2646
 
                        }
2647
 
                }
2648
 
 
2649
 
                gendata.left = mleft;
2650
 
                gendata.right = mright;
2651
 
 
2652
 
                return;
2653
 
        }
2654
 
 
2655
 
        /* Calculate buffer margins for a black head. This is
2656
 
         * almost exactly the same as before, but now we do
2657
 
         * a single pass because we have only one black pen.
2658
 
         */
2659
 
        if(gendata.rendermode == LXM3200_M)
2660
 
        {
2661
 
                /* Monochromatic mode: we use 208 nozzles and
2662
 
                 * all the buffer, so the initial offset is zero.
2663
 
                 */
2664
 
 
2665
 
                scan = gendata.scanbuf;
2666
 
                calclinemargins(scan, BLACK, &mleft, &mright);
2667
 
 
2668
 
                for(i=1; i<gendata.numblines; i++)
2669
 
                {
2670
 
                        scan += gendata.numbytes;
2671
 
                        calclinemargins(scan, BLACK, &l1, &r1);
2672
 
                        mleft = min(mleft, l1);
2673
 
                        mright = max(mright, r1);
2674
 
                }
2675
 
 
2676
 
                gendata.left = mleft;
2677
 
                gendata.right = mright;
2678
 
 
2679
 
                return;
2680
 
        }
2681
 
 
2682
 
        /* Standard color mode: we use 192 nozzles and must 
2683
 
         * take into account the vertical alignment.
2684
 
         */
2685
 
        
2686
 
        nl = (gendata.numlines * 2) / gendata.yrmul;
2687
 
        q = gendata.firstline + valign[BLACKVALIGN];
2688
 
 
2689
 
        scan = gendata.scanbuf + (q & cmask)*gendata.numbytes;
2690
 
        calclinemargins(scan, BLACK, &mleft, &mright);
2691
 
 
2692
 
        for(i=1; i<nl; i++)
2693
 
        {
2694
 
                scan = gendata.scanbuf + ((q+i) & cmask)*gendata.numbytes;
2695
 
                calclinemargins(scan, BLACK, &l1, &r1);
2696
 
                mleft = min(mleft, l1);
2697
 
                mright = max(mright, r1);
2698
 
        }
2699
 
        gendata.left = mleft;
2700
 
        gendata.right = mright; 
 
2604
        int i, l1, r1, q, k;
 
2605
        int mleft, mright, nl;
 
2606
        int cpen, cmask, al;
 
2607
        byte *scan;
 
2608
 
 
2609
        /* Adjust mask and pen height according to vertical resolution */
 
2610
        cpen = (COLORPEN * 2) / gendata.yrmul;
 
2611
        cmask = (gendata.numblines) - 1;
 
2612
 
 
2613
        /* Calculate margins for a color or photo cartridge */
 
2614
        if(head == RIGHT || (gendata.rendermode == LXM3200_P))
 
2615
        {
 
2616
                /* Get correct vertical aligment */
 
2617
                al = (head == LEFT ? PHOTOVALIGN : COLORVALIGN);
 
2618
 
 
2619
                q = gendata.firstline + valign[al];
 
2620
 
 
2621
                /* Calculate margins for first line, using those values
 
2622
                 * to initialize the max and min values.
 
2623
                 */
 
2624
                scan = gendata.scanbuf + ((q+penofs[0]) & cmask)*gendata.numbytes;
 
2625
                calclinemargins(scan, colmask[head][0], &mleft, &mright);
 
2626
 
 
2627
                /* And now scan all the remaining buffer. We scan according
 
2628
                 * to color pens, i.e. we calculate the margin on the rows
 
2629
                 * where magenta will be laid down taking into account magenta
 
2630
                 * pixels only, and this will be the magenta submargin. After
 
2631
                 * having done that for cyan and yellow as well, we take as the
 
2632
                 * global margin the smaller space that contains all the three
 
2633
                 * submargins.
 
2634
                 */
 
2635
                for(k=0; k<3; k++)
 
2636
                {
 
2637
                        for(i=0; i<cpen; i++)
 
2638
                        {
 
2639
                                scan = gendata.scanbuf + ((q+i+penofs[k]) & cmask)*gendata.numbytes;
 
2640
                                calclinemargins(scan, colmask[head][k], &l1, &r1);
 
2641
                                mleft = min(mleft, l1);
 
2642
                                mright = max(mright, r1);
 
2643
                        }
 
2644
                }
 
2645
 
 
2646
                gendata.left = mleft;
 
2647
                gendata.right = mright;
 
2648
 
 
2649
                return;
 
2650
        }
 
2651
 
 
2652
        /* Calculate buffer margins for a black head. This is
 
2653
         * almost exactly the same as before, but now we do
 
2654
         * a single pass because we have only one black pen.
 
2655
         */
 
2656
        if(gendata.rendermode == LXM3200_M)
 
2657
        {
 
2658
                /* Monochromatic mode: we use 208 nozzles and
 
2659
                 * all the buffer, so the initial offset is zero.
 
2660
                 */
 
2661
 
 
2662
                scan = gendata.scanbuf;
 
2663
                calclinemargins(scan, BLACK, &mleft, &mright);
 
2664
 
 
2665
                for(i=1; i<gendata.numblines; i++)
 
2666
                {
 
2667
                        scan += gendata.numbytes;
 
2668
                        calclinemargins(scan, BLACK, &l1, &r1);
 
2669
                        mleft = min(mleft, l1);
 
2670
                        mright = max(mright, r1);
 
2671
                }
 
2672
 
 
2673
                gendata.left = mleft;
 
2674
                gendata.right = mright;
 
2675
 
 
2676
                return;
 
2677
        }
 
2678
 
 
2679
        /* Standard color mode: we use 192 nozzles and must
 
2680
         * take into account the vertical alignment.
 
2681
         */
 
2682
 
 
2683
        nl = (gendata.numlines * 2) / gendata.yrmul;
 
2684
        q = gendata.firstline + valign[BLACKVALIGN];
 
2685
 
 
2686
        scan = gendata.scanbuf + (q & cmask)*gendata.numbytes;
 
2687
        calclinemargins(scan, BLACK, &mleft, &mright);
 
2688
 
 
2689
        for(i=1; i<nl; i++)
 
2690
        {
 
2691
                scan = gendata.scanbuf + ((q+i) & cmask)*gendata.numbytes;
 
2692
                calclinemargins(scan, BLACK, &l1, &r1);
 
2693
                mleft = min(mleft, l1);
 
2694
                mright = max(mright, r1);
 
2695
        }
 
2696
        gendata.left = mleft;
 
2697
        gendata.right = mright;
2701
2698
}
2702
2699
 
2703
2700
/*
2707
2704
static void
2708
2705
print_color_page(void)
2709
2706
{
2710
 
        int res, lline, cmask;
2711
 
        int i, j, nl, q, sk;
2712
 
        byte *scan;
2713
 
 
2714
 
        /* Set the blackskip value depending on vertical resolution.
2715
 
         * Since we have a black pen which is 3 times as high as
2716
 
         * each color pen, we must print black only once every three 
2717
 
         * passes. So we take into account on which line we printed
2718
 
         * the last black stripe and then we print another only if
2719
 
         * the current line is at least "sk" lines after that.
2720
 
         */
2721
 
        sk = (BWCOLPEN * 2) / gendata.yrmul;
2722
 
        
2723
 
        /* Get the first buffer, and if it's empty continue
2724
 
         * to skip forward without doing anything.
2725
 
         */
2726
 
        res = init_buffer();
2727
 
        while(res == 0)res = roll_buffer();
2728
 
 
2729
 
        /* If this buffer happens to be the last one, 
2730
 
         * and empty as well, we had a blank page. 
2731
 
         * Just exit without ado.
2732
 
         */
2733
 
        if(res == LAST)return;
2734
 
 
2735
 
        /* This is the first non-blank line of the
2736
 
         * page: issue a vertical skip command to
2737
 
         * advance the paper to proper position.
2738
 
         */
2739
 
        skiplines(gendata.curvline, COLTOPSTART);
2740
 
 
2741
 
        /* "lline" holds the number of the first line of
2742
 
         * the last buffer printed, either with left or 
2743
 
         * right head. This is needed to keep track of 
2744
 
         * how many lines we must skip from one stripe to 
2745
 
         * the next (if we encounter blank buffers we just
2746
 
         * ignore them without moving the head, so we need
2747
 
         * to do the proper vertical motion in one single
2748
 
         * pass as soon as we encounter a non-blank buffer). 
2749
 
         */
2750
 
        lline = gendata.curvline;
2751
 
        
2752
 
        /* Now depending on the data we have into the 
2753
 
         * buffer, print with the left head, right
2754
 
         * head or both.
2755
 
         * NOTE: this is the first buffer, and it needs
2756
 
         * to be treated specially from the others.
2757
 
         * The main difference is that we usually finalize
2758
 
         * the buffer (issuing the print commands) at the
2759
 
         * start of the next buffer, and not at the end of
2760
 
         * the current one. This is because the Lexmark 3200
2761
 
         * wants to know where to leave the printing head
2762
 
         * at the end of each printing command, but we can't
2763
 
         * know that until we start the next buffer so discovering
2764
 
         * its margins and position. The solution is that we keep
2765
 
         * "suspended" each buffer until we find another valid one.
2766
 
         * The first buffer is special since there is no previous
2767
 
         * buffer to finalize.
2768
 
         * NOTE: I will comment the general case below, because
2769
 
         * this code is simply a subset of the main loop.
2770
 
         */
2771
 
        switch(res)
2772
 
        {
2773
 
                case LHDATA:
2774
 
                        calcbufmargins(LEFT);
2775
 
                        gendata.ileave = 0;
2776
 
                        encode_bw_buf();
2777
 
                        gendata.lastblack = gendata.curvline + sk;
2778
 
                        lline = gendata.curvline;
2779
 
                        if(gendata.yres == 1200)
2780
 
                        {
2781
 
                                finalizeheader(1, LEFT);
2782
 
                                gendata.ileave = 1;
2783
 
                                encode_bw_buf();
2784
 
                                lline++;
2785
 
                        }
2786
 
                        break;
2787
 
 
2788
 
                case RHDATA:
2789
 
                        calcbufmargins(RIGHT);
2790
 
                        gendata.ileave = 0;
2791
 
                        encode_col_buf(RIGHT);
2792
 
                        lline = gendata.curvline;
2793
 
                        if(gendata.yres == 1200)
2794
 
                        {
2795
 
                                finalizeheader(1, RIGHT);
2796
 
                                gendata.ileave = 1;
2797
 
                                encode_col_buf(RIGHT);
2798
 
                                lline++;
2799
 
                        }
2800
 
                        break;
2801
 
 
2802
 
                case LHDATA|RHDATA:
2803
 
                        calcbufmargins(LEFT);
2804
 
                        gendata.ileave = 0;
2805
 
                        encode_bw_buf();
2806
 
                        gendata.lastblack = gendata.curvline + sk;
2807
 
                        calcbufmargins(RIGHT);
2808
 
                        finalizeheader(0, RIGHT);
2809
 
                        encode_col_buf(RIGHT);
2810
 
                        lline = gendata.curvline;
2811
 
                        if(gendata.yres == 1200)
2812
 
                        {
2813
 
                                calcbufmargins(LEFT);
2814
 
                                finalizeheader(1, LEFT);
2815
 
                                gendata.ileave = 1;
2816
 
                                encode_bw_buf();
2817
 
                                calcbufmargins(RIGHT);
2818
 
                                finalizeheader(0, RIGHT);
2819
 
                                encode_col_buf(RIGHT);
2820
 
                                lline++;
2821
 
                        }
2822
 
                        break;
2823
 
        }
2824
 
 
2825
 
        /* Skip to next buffer */
2826
 
        res = roll_buffer();
2827
 
 
2828
 
        /* Start the main loop. Here we do all the stuff required
2829
 
         * to print buffers properly.
2830
 
         */
2831
 
        while(!(res & LAST))
2832
 
        {
2833
 
                /* If we haven't forwarded until "lastblack", do not
2834
 
                 * print black data because it has been printed on
2835
 
                 * previous passes. So, if we are below gendata.lastblack
2836
 
                 * clear the LHDATA flag to ignore left-head data.
2837
 
                 */
2838
 
                if(gendata.curvline < gendata.lastblack)res &= ~LHDATA;
2839
 
 
2840
 
                /* And now start examining the buffer for data */
2841
 
                switch(res)
2842
 
                {
2843
 
                        /* We have left head data */
2844
 
                        case LHDATA:
2845
 
 
2846
 
                                /* Calculate the margins of this buffer */
2847
 
                                calcbufmargins(LEFT);
2848
 
 
2849
 
                                /* And then finalize the previous buffer. We can't 
2850
 
                                 * do this until now, because only now we know the 
2851
 
                                 * margins and vertical position of the next buffer,
2852
 
                                 * which are required data to calculate the final 
2853
 
                                 * head position at the end of the previous buffer.
2854
 
                                 */
2855
 
                                finalizeheader(gendata.curvline - lline, LEFT);
2856
 
 
2857
 
                                /* Set interleave to zero (only meaningful in 1200dpi
2858
 
                                 * vertical mode.
2859
 
                                 */
2860
 
                                gendata.ileave = 0;
2861
 
 
2862
 
                                /* Encode this buffer making it the current buffer */
2863
 
                                encode_bw_buf();
2864
 
                                
2865
 
                                /* Since we are printing a black buffer, update
2866
 
                                 * gendata.lastblack to point to the first line
2867
 
                                 * not covered by this black pass.
2868
 
                                 */
2869
 
                                gendata.lastblack = gendata.curvline + sk;
2870
 
 
2871
 
                                /* And update "lline" as well */
2872
 
                                lline = gendata.curvline;
2873
 
 
2874
 
                                /* If we are printing at 1200 dpi vertical, we must
2875
 
                                 * do one more pass, interleaved with the one before.
2876
 
                                 */
2877
 
                                if(gendata.yres == 1200)
2878
 
                                {
2879
 
                                        /* Finalize previous buffer, moving down 1/1200th
2880
 
                                         * of an inch to properly interleave the two passes.
2881
 
                                         * This is naive: we should do something here, because
2882
 
                                         * this way two adjacent lines are printed by the same
2883
 
                                         * nozzle, and there is the danger of having a slight
2884
 
                                         * banding on output (no more than 1/600th of an inch,
2885
 
                                         * but maybe noticeable).
2886
 
                                         */
2887
 
                                        finalizeheader(1, LEFT);
2888
 
 
2889
 
                                        /* Set interleave to 1 to start an interleaved pass */
2890
 
                                        gendata.ileave = 1;
2891
 
                                        
2892
 
                                        /* Encode the buffer, and not finalize it: we leave
2893
 
                                         * the buffer suspended until we find another buffer
2894
 
                                         * to print.
2895
 
                                         */
2896
 
                                        encode_bw_buf();
2897
 
 
2898
 
                                        /* And adjust "lline" because to print the interleaved
2899
 
                                         * pass we have moved down one line, so we need to 
2900
 
                                         * skip one line less to print the next buffer.
2901
 
                                         */
2902
 
                                        lline++;
2903
 
                                }
2904
 
                                break;
2905
 
 
2906
 
                        /* Right head data. This is absolutely identical to the
2907
 
                         * code above for left head data, with two exceptions: all
2908
 
                         * the "LEFT" codes are changed to "RIGHT" and we don't
2909
 
                         * update gendata.lastblack because we are printing a
2910
 
                         * color stripe and not a black one.
2911
 
                         */
2912
 
                  case RHDATA:
2913
 
                                calcbufmargins(RIGHT);
2914
 
                                finalizeheader(gendata.curvline - lline, RIGHT);
2915
 
                                gendata.ileave = 0;
2916
 
                                encode_col_buf(RIGHT);
2917
 
                                lline = gendata.curvline;
2918
 
                                if(gendata.yres == 1200)
2919
 
                                {
2920
 
                                        finalizeheader(1, RIGHT);
2921
 
                                        gendata.ileave = 1;
2922
 
                                        encode_col_buf(RIGHT);
2923
 
                                        lline++;
2924
 
                                }
2925
 
                                break;
2926
 
                                
2927
 
                        /* We have both left and right head data (i.e. black and
2928
 
                         * color on the same stripe).
2929
 
                         * The code here is identical to the code for the left data
2930
 
                         * only and right data only cases above. But they are
2931
 
                         * interleaved, because since we can't take back the paper
2932
 
                         * once it's advanced, in case we are printing at 1200 dpi
2933
 
                         * vertical (and so we need two interlaced passes) we need
2934
 
                         * to do both the first black and the first color pass,
2935
 
                         * advance the paper and then do the second black and the
2936
 
                         * second color pass. Simply appendig the two code pieces
2937
 
                         * above would not work.
2938
 
                         */
2939
 
                        case LHDATA|RHDATA:
2940
 
                                calcbufmargins(LEFT);
2941
 
                                finalizeheader(gendata.curvline - lline, LEFT);
2942
 
                                gendata.ileave = 0;
2943
 
                                encode_bw_buf();
2944
 
                                gendata.lastblack = gendata.curvline + sk;
2945
 
                                calcbufmargins(RIGHT);
2946
 
                                finalizeheader(0, RIGHT);
2947
 
                                encode_col_buf(RIGHT);
2948
 
                                lline = gendata.curvline;               
2949
 
                                if(gendata.yres == 1200)
2950
 
                                {
2951
 
                                        calcbufmargins(LEFT);
2952
 
                                        finalizeheader(1, LEFT);
2953
 
                                        gendata.ileave = 1;
2954
 
                                        encode_bw_buf();
2955
 
                                        calcbufmargins(RIGHT);
2956
 
                                        finalizeheader(0, RIGHT);
2957
 
                                        encode_col_buf(RIGHT);
2958
 
                                        lline++;
2959
 
                                }
2960
 
                                break;
2961
 
                }
2962
 
                
2963
 
                /* Get another buffer */
2964
 
                res = roll_buffer();
2965
 
        }
2966
 
        
2967
 
        /* Last buffer. We treat this one specially as well,
2968
 
         * because we don't have a subsequent buffer to print,
2969
 
         * and so we need to finalize this buffers as soon as
2970
 
         * possible.
2971
 
         */
2972
 
        res = qualify_buffer();
2973
 
 
2974
 
        /* Void the printed blacks. Since we are printing the
2975
 
         * last buffer, it could happen that we have advanced
2976
 
         * from the last time we printed a black stripe but
2977
 
         * we are not yet at the point where another black
2978
 
         * stripe would have been triggered. This would cause
2979
 
         * an eventual black component in the last lines of
2980
 
         * the page to be ignored.
2981
 
         * To avoid the problem we do an unconditional black
2982
 
         * pass, but we also must clear the black bits from the
2983
 
         * lines we have already printed otherwise we would
2984
 
         * print them twice.
2985
 
         */
2986
 
        if((res & LHDATA) && (gendata.curvline <= gendata.lastblack))
2987
 
        { 
2988
 
                /* Find how many black lines we have yet printed
2989
 
                 * are still in the buffer
2990
 
                 */
2991
 
                nl = gendata.lastblack - gendata.curvline;
2992
 
 
2993
 
                /* And now remove the BLACK bit from them */
2994
 
 
2995
 
                q = gendata.firstline + valign[BLACKVALIGN];
2996
 
                cmask = (gendata.numblines) - 1;        
2997
 
                for(i=0; i<nl; i++)
2998
 
                {
2999
 
                        scan = gendata.scanbuf + ((i+q) & cmask)*gendata.numbytes;
3000
 
                        for(j=0; j<gendata.numbytes; j++)
3001
 
                        {
3002
 
                                *scan &= ~BLACK;
3003
 
                                scan++;
3004
 
                        }
3005
 
                }
3006
 
        }
3007
 
        
3008
 
        /* Now we can print the last buffer as usual.
3009
 
         * This is perfectly identical to the code
3010
 
         * into the loop above: we are replicating it 
3011
 
         * only because we need the blanking code above
3012
 
         * to be executed before this code.
3013
 
         * Maybe there is a better way to do it...
3014
 
         */
3015
 
        switch(res)
3016
 
        {       
3017
 
                case LHDATA:
3018
 
                        calcbufmargins(LEFT);
3019
 
                        finalizeheader(gendata.curvline - lline, LEFT);
3020
 
                        gendata.ileave = 0;
3021
 
                        encode_bw_buf();
3022
 
                        if(gendata.yres == 1200)
3023
 
                        {
3024
 
                                finalizeheader(1, LEFT);
3025
 
                                gendata.ileave = 1;
3026
 
                                encode_bw_buf();
3027
 
                                lline++;
3028
 
                        }
3029
 
                        break;
3030
 
                        
3031
 
                case RHDATA:
3032
 
                        calcbufmargins(RIGHT);
3033
 
                        finalizeheader(gendata.curvline - lline, RIGHT);
3034
 
                        gendata.ileave = 0;
3035
 
                        encode_col_buf(RIGHT);
3036
 
                        if(gendata.yres == 1200)
3037
 
                        {
3038
 
                                finalizeheader(1, RIGHT);
3039
 
                                gendata.ileave = 1;
3040
 
                                encode_col_buf(RIGHT);
3041
 
                                lline++;
3042
 
                        }
3043
 
                        break;
3044
 
                                
3045
 
                case LHDATA|RHDATA:
3046
 
                        calcbufmargins(LEFT);
3047
 
                        finalizeheader(gendata.curvline - lline, LEFT);
3048
 
                        gendata.ileave = 0;
3049
 
                        encode_bw_buf();
3050
 
                        calcbufmargins(RIGHT);
3051
 
                        finalizeheader(0, RIGHT);
3052
 
                        encode_col_buf(RIGHT);
3053
 
                        if(gendata.yres == 1200)
3054
 
                        {
3055
 
                                calcbufmargins(LEFT);
3056
 
                                finalizeheader(1, LEFT);
3057
 
                                gendata.ileave = 1;
3058
 
                                encode_bw_buf();
3059
 
                                calcbufmargins(RIGHT);
3060
 
                                finalizeheader(0, RIGHT);
3061
 
                                encode_col_buf(RIGHT);
3062
 
                                lline++;
3063
 
                        }
3064
 
                        break;
3065
 
        }
3066
 
 
3067
 
        /* Now finalize the header using a value of "0" for
3068
 
         * the vertical skip (no need to move down: the
3069
 
         * paper is about to be ejected) and -1 for the
3070
 
         * head (meaning: last buffer, don't care for the
3071
 
         * final head position, it will be reset unconditionally
3072
 
         * by the trailing sequence).
3073
 
         */
3074
 
        finalizeheader(0, -1);
 
2707
        int res, lline, cmask;
 
2708
        int i, j, nl, q, sk;
 
2709
        byte *scan;
 
2710
 
 
2711
        /* Set the blackskip value depending on vertical resolution.
 
2712
         * Since we have a black pen which is 3 times as high as
 
2713
         * each color pen, we must print black only once every three
 
2714
         * passes. So we take into account on which line we printed
 
2715
         * the last black stripe and then we print another only if
 
2716
         * the current line is at least "sk" lines after that.
 
2717
         */
 
2718
        sk = (BWCOLPEN * 2) / gendata.yrmul;
 
2719
 
 
2720
        /* Get the first buffer, and if it's empty continue
 
2721
         * to skip forward without doing anything.
 
2722
         */
 
2723
        res = init_buffer();
 
2724
        while(res == 0)res = roll_buffer();
 
2725
 
 
2726
        /* If this buffer happens to be the last one,
 
2727
         * and empty as well, we had a blank page.
 
2728
         * Just exit without ado.
 
2729
         */
 
2730
        if(res == LAST)return;
 
2731
 
 
2732
        /* This is the first non-blank line of the
 
2733
         * page: issue a vertical skip command to
 
2734
         * advance the paper to proper position.
 
2735
         */
 
2736
        skiplines(gendata.curvline, COLTOPSTART);
 
2737
 
 
2738
        /* "lline" holds the number of the first line of
 
2739
         * the last buffer printed, either with left or
 
2740
         * right head. This is needed to keep track of
 
2741
         * how many lines we must skip from one stripe to
 
2742
         * the next (if we encounter blank buffers we just
 
2743
         * ignore them without moving the head, so we need
 
2744
         * to do the proper vertical motion in one single
 
2745
         * pass as soon as we encounter a non-blank buffer).
 
2746
         */
 
2747
        lline = gendata.curvline;
 
2748
 
 
2749
        /* Now depending on the data we have into the
 
2750
         * buffer, print with the left head, right
 
2751
         * head or both.
 
2752
         * NOTE: this is the first buffer, and it needs
 
2753
         * to be treated specially from the others.
 
2754
         * The main difference is that we usually finalize
 
2755
         * the buffer (issuing the print commands) at the
 
2756
         * start of the next buffer, and not at the end of
 
2757
         * the current one. This is because the Lexmark 3200
 
2758
         * wants to know where to leave the printing head
 
2759
         * at the end of each printing command, but we can't
 
2760
         * know that until we start the next buffer so discovering
 
2761
         * its margins and position. The solution is that we keep
 
2762
         * "suspended" each buffer until we find another valid one.
 
2763
         * The first buffer is special since there is no previous
 
2764
         * buffer to finalize.
 
2765
         * NOTE: I will comment the general case below, because
 
2766
         * this code is simply a subset of the main loop.
 
2767
         */
 
2768
        switch(res)
 
2769
        {
 
2770
                case LHDATA:
 
2771
                        calcbufmargins(LEFT);
 
2772
                        gendata.ileave = 0;
 
2773
                        encode_bw_buf();
 
2774
                        gendata.lastblack = gendata.curvline + sk;
 
2775
                        lline = gendata.curvline;
 
2776
                        if(gendata.yres == 1200)
 
2777
                        {
 
2778
                                finalizeheader(1, LEFT);
 
2779
                                gendata.ileave = 1;
 
2780
                                encode_bw_buf();
 
2781
                                lline++;
 
2782
                        }
 
2783
                        break;
 
2784
 
 
2785
                case RHDATA:
 
2786
                        calcbufmargins(RIGHT);
 
2787
                        gendata.ileave = 0;
 
2788
                        encode_col_buf(RIGHT);
 
2789
                        lline = gendata.curvline;
 
2790
                        if(gendata.yres == 1200)
 
2791
                        {
 
2792
                                finalizeheader(1, RIGHT);
 
2793
                                gendata.ileave = 1;
 
2794
                                encode_col_buf(RIGHT);
 
2795
                                lline++;
 
2796
                        }
 
2797
                        break;
 
2798
 
 
2799
                case LHDATA|RHDATA:
 
2800
                        calcbufmargins(LEFT);
 
2801
                        gendata.ileave = 0;
 
2802
                        encode_bw_buf();
 
2803
                        gendata.lastblack = gendata.curvline + sk;
 
2804
                        calcbufmargins(RIGHT);
 
2805
                        finalizeheader(0, RIGHT);
 
2806
                        encode_col_buf(RIGHT);
 
2807
                        lline = gendata.curvline;
 
2808
                        if(gendata.yres == 1200)
 
2809
                        {
 
2810
                                calcbufmargins(LEFT);
 
2811
                                finalizeheader(1, LEFT);
 
2812
                                gendata.ileave = 1;
 
2813
                                encode_bw_buf();
 
2814
                                calcbufmargins(RIGHT);
 
2815
                                finalizeheader(0, RIGHT);
 
2816
                                encode_col_buf(RIGHT);
 
2817
                                lline++;
 
2818
                        }
 
2819
                        break;
 
2820
        }
 
2821
 
 
2822
        /* Skip to next buffer */
 
2823
        res = roll_buffer();
 
2824
 
 
2825
        /* Start the main loop. Here we do all the stuff required
 
2826
         * to print buffers properly.
 
2827
         */
 
2828
        while(!(res & LAST))
 
2829
        {
 
2830
                /* If we haven't forwarded until "lastblack", do not
 
2831
                 * print black data because it has been printed on
 
2832
                 * previous passes. So, if we are below gendata.lastblack
 
2833
                 * clear the LHDATA flag to ignore left-head data.
 
2834
                 */
 
2835
                if(gendata.curvline < gendata.lastblack)res &= ~LHDATA;
 
2836
 
 
2837
                /* And now start examining the buffer for data */
 
2838
                switch(res)
 
2839
                {
 
2840
                        /* We have left head data */
 
2841
                        case LHDATA:
 
2842
 
 
2843
                                /* Calculate the margins of this buffer */
 
2844
                                calcbufmargins(LEFT);
 
2845
 
 
2846
                                /* And then finalize the previous buffer. We can't
 
2847
                                 * do this until now, because only now we know the
 
2848
                                 * margins and vertical position of the next buffer,
 
2849
                                 * which are required data to calculate the final
 
2850
                                 * head position at the end of the previous buffer.
 
2851
                                 */
 
2852
                                finalizeheader(gendata.curvline - lline, LEFT);
 
2853
 
 
2854
                                /* Set interleave to zero (only meaningful in 1200dpi
 
2855
                                 * vertical mode.
 
2856
                                 */
 
2857
                                gendata.ileave = 0;
 
2858
 
 
2859
                                /* Encode this buffer making it the current buffer */
 
2860
                                encode_bw_buf();
 
2861
 
 
2862
                                /* Since we are printing a black buffer, update
 
2863
                                 * gendata.lastblack to point to the first line
 
2864
                                 * not covered by this black pass.
 
2865
                                 */
 
2866
                                gendata.lastblack = gendata.curvline + sk;
 
2867
 
 
2868
                                /* And update "lline" as well */
 
2869
                                lline = gendata.curvline;
 
2870
 
 
2871
                                /* If we are printing at 1200 dpi vertical, we must
 
2872
                                 * do one more pass, interleaved with the one before.
 
2873
                                 */
 
2874
                                if(gendata.yres == 1200)
 
2875
                                {
 
2876
                                        /* Finalize previous buffer, moving down 1/1200th
 
2877
                                         * of an inch to properly interleave the two passes.
 
2878
                                         * This is naive: we should do something here, because
 
2879
                                         * this way two adjacent lines are printed by the same
 
2880
                                         * nozzle, and there is the danger of having a slight
 
2881
                                         * banding on output (no more than 1/600th of an inch,
 
2882
                                         * but maybe noticeable).
 
2883
                                         */
 
2884
                                        finalizeheader(1, LEFT);
 
2885
 
 
2886
                                        /* Set interleave to 1 to start an interleaved pass */
 
2887
                                        gendata.ileave = 1;
 
2888
 
 
2889
                                        /* Encode the buffer, and not finalize it: we leave
 
2890
                                         * the buffer suspended until we find another buffer
 
2891
                                         * to print.
 
2892
                                         */
 
2893
                                        encode_bw_buf();
 
2894
 
 
2895
                                        /* And adjust "lline" because to print the interleaved
 
2896
                                         * pass we have moved down one line, so we need to
 
2897
                                         * skip one line less to print the next buffer.
 
2898
                                         */
 
2899
                                        lline++;
 
2900
                                }
 
2901
                                break;
 
2902
 
 
2903
                        /* Right head data. This is absolutely identical to the
 
2904
                         * code above for left head data, with two exceptions: all
 
2905
                         * the "LEFT" codes are changed to "RIGHT" and we don't
 
2906
                         * update gendata.lastblack because we are printing a
 
2907
                         * color stripe and not a black one.
 
2908
                         */
 
2909
                  case RHDATA:
 
2910
                                calcbufmargins(RIGHT);
 
2911
                                finalizeheader(gendata.curvline - lline, RIGHT);
 
2912
                                gendata.ileave = 0;
 
2913
                                encode_col_buf(RIGHT);
 
2914
                                lline = gendata.curvline;
 
2915
                                if(gendata.yres == 1200)
 
2916
                                {
 
2917
                                        finalizeheader(1, RIGHT);
 
2918
                                        gendata.ileave = 1;
 
2919
                                        encode_col_buf(RIGHT);
 
2920
                                        lline++;
 
2921
                                }
 
2922
                                break;
 
2923
 
 
2924
                        /* We have both left and right head data (i.e. black and
 
2925
                         * color on the same stripe).
 
2926
                         * The code here is identical to the code for the left data
 
2927
                         * only and right data only cases above. But they are
 
2928
                         * interleaved, because since we can't take back the paper
 
2929
                         * once it's advanced, in case we are printing at 1200 dpi
 
2930
                         * vertical (and so we need two interlaced passes) we need
 
2931
                         * to do both the first black and the first color pass,
 
2932
                         * advance the paper and then do the second black and the
 
2933
                         * second color pass. Simply appendig the two code pieces
 
2934
                         * above would not work.
 
2935
                         */
 
2936
                        case LHDATA|RHDATA:
 
2937
                                calcbufmargins(LEFT);
 
2938
                                finalizeheader(gendata.curvline - lline, LEFT);
 
2939
                                gendata.ileave = 0;
 
2940
                                encode_bw_buf();
 
2941
                                gendata.lastblack = gendata.curvline + sk;
 
2942
                                calcbufmargins(RIGHT);
 
2943
                                finalizeheader(0, RIGHT);
 
2944
                                encode_col_buf(RIGHT);
 
2945
                                lline = gendata.curvline;
 
2946
                                if(gendata.yres == 1200)
 
2947
                                {
 
2948
                                        calcbufmargins(LEFT);
 
2949
                                        finalizeheader(1, LEFT);
 
2950
                                        gendata.ileave = 1;
 
2951
                                        encode_bw_buf();
 
2952
                                        calcbufmargins(RIGHT);
 
2953
                                        finalizeheader(0, RIGHT);
 
2954
                                        encode_col_buf(RIGHT);
 
2955
                                        lline++;
 
2956
                                }
 
2957
                                break;
 
2958
                }
 
2959
 
 
2960
                /* Get another buffer */
 
2961
                res = roll_buffer();
 
2962
        }
 
2963
 
 
2964
        /* Last buffer. We treat this one specially as well,
 
2965
         * because we don't have a subsequent buffer to print,
 
2966
         * and so we need to finalize this buffers as soon as
 
2967
         * possible.
 
2968
         */
 
2969
        res = qualify_buffer();
 
2970
 
 
2971
        /* Void the printed blacks. Since we are printing the
 
2972
         * last buffer, it could happen that we have advanced
 
2973
         * from the last time we printed a black stripe but
 
2974
         * we are not yet at the point where another black
 
2975
         * stripe would have been triggered. This would cause
 
2976
         * an eventual black component in the last lines of
 
2977
         * the page to be ignored.
 
2978
         * To avoid the problem we do an unconditional black
 
2979
         * pass, but we also must clear the black bits from the
 
2980
         * lines we have already printed otherwise we would
 
2981
         * print them twice.
 
2982
         */
 
2983
        if((res & LHDATA) && (gendata.curvline <= gendata.lastblack))
 
2984
        {
 
2985
                /* Find how many black lines we have yet printed
 
2986
                 * are still in the buffer
 
2987
                 */
 
2988
                nl = gendata.lastblack - gendata.curvline;
 
2989
 
 
2990
                /* And now remove the BLACK bit from them */
 
2991
 
 
2992
                q = gendata.firstline + valign[BLACKVALIGN];
 
2993
                cmask = (gendata.numblines) - 1;
 
2994
                for(i=0; i<nl; i++)
 
2995
                {
 
2996
                        scan = gendata.scanbuf + ((i+q) & cmask)*gendata.numbytes;
 
2997
                        for(j=0; j<gendata.numbytes; j++)
 
2998
                        {
 
2999
                                *scan &= ~BLACK;
 
3000
                                scan++;
 
3001
                        }
 
3002
                }
 
3003
        }
 
3004
 
 
3005
        /* Now we can print the last buffer as usual.
 
3006
         * This is perfectly identical to the code
 
3007
         * into the loop above: we are replicating it
 
3008
         * only because we need the blanking code above
 
3009
         * to be executed before this code.
 
3010
         * Maybe there is a better way to do it...
 
3011
         */
 
3012
        switch(res)
 
3013
        {
 
3014
                case LHDATA:
 
3015
                        calcbufmargins(LEFT);
 
3016
                        finalizeheader(gendata.curvline - lline, LEFT);
 
3017
                        gendata.ileave = 0;
 
3018
                        encode_bw_buf();
 
3019
                        if(gendata.yres == 1200)
 
3020
                        {
 
3021
                                finalizeheader(1, LEFT);
 
3022
                                gendata.ileave = 1;
 
3023
                                encode_bw_buf();
 
3024
                                lline++;
 
3025
                        }
 
3026
                        break;
 
3027
 
 
3028
                case RHDATA:
 
3029
                        calcbufmargins(RIGHT);
 
3030
                        finalizeheader(gendata.curvline - lline, RIGHT);
 
3031
                        gendata.ileave = 0;
 
3032
                        encode_col_buf(RIGHT);
 
3033
                        if(gendata.yres == 1200)
 
3034
                        {
 
3035
                                finalizeheader(1, RIGHT);
 
3036
                                gendata.ileave = 1;
 
3037
                                encode_col_buf(RIGHT);
 
3038
                                lline++;
 
3039
                        }
 
3040
                        break;
 
3041
 
 
3042
                case LHDATA|RHDATA:
 
3043
                        calcbufmargins(LEFT);
 
3044
                        finalizeheader(gendata.curvline - lline, LEFT);
 
3045
                        gendata.ileave = 0;
 
3046
                        encode_bw_buf();
 
3047
                        calcbufmargins(RIGHT);
 
3048
                        finalizeheader(0, RIGHT);
 
3049
                        encode_col_buf(RIGHT);
 
3050
                        if(gendata.yres == 1200)
 
3051
                        {
 
3052
                                calcbufmargins(LEFT);
 
3053
                                finalizeheader(1, LEFT);
 
3054
                                gendata.ileave = 1;
 
3055
                                encode_bw_buf();
 
3056
                                calcbufmargins(RIGHT);
 
3057
                                finalizeheader(0, RIGHT);
 
3058
                                encode_col_buf(RIGHT);
 
3059
                                lline++;
 
3060
                        }
 
3061
                        break;
 
3062
        }
 
3063
 
 
3064
        /* Now finalize the header using a value of "0" for
 
3065
         * the vertical skip (no need to move down: the
 
3066
         * paper is about to be ejected) and -1 for the
 
3067
         * head (meaning: last buffer, don't care for the
 
3068
         * final head position, it will be reset unconditionally
 
3069
         * by the trailing sequence).
 
3070
         */
 
3071
        finalizeheader(0, -1);
3075
3072
}
3076
3073
 
3077
 
/* This is the equivalent of print_color_page() 
 
3074
/* This is the equivalent of print_color_page()
3078
3075
 * for monochrome output. It is almost identical,
3079
3076
 * only much simpler because now we are printing
3080
3077
 * with only one head.
3081
3078
 */
3082
3079
static void
3083
3080
print_mono_page(void)
3084
 
{       
3085
 
        int res, lline;
3086
 
 
3087
 
        /* Load the first buffer, skipping over
3088
 
         * blank lines (if any).
3089
 
         */
3090
 
        res = init_buffer();
3091
 
        
3092
 
        /* If we happen to have a buffer which is LAST
3093
 
         * and empty, we have a blank page to print:
3094
 
         * just say goodbye.
3095
 
         */
3096
 
        if(res == LAST)return;
3097
 
 
3098
 
        /* Skip enough lines to reach the start of
3099
 
         * the first stripe to print.
3100
 
         */
3101
 
        skiplines(gendata.curvline, BWTOPSTART);
3102
 
        lline = gendata.curvline;
3103
 
        
3104
 
        /* And now print the first buffer. This part of
3105
 
         * the code is identical to the LHDATA part in
3106
 
         * print_color_page()
3107
 
         */
3108
 
        calcbufmargins(LEFT);
3109
 
        gendata.ileave = 0;
3110
 
        encode_bw_buf();
3111
 
        lline = gendata.curvline;
3112
 
        if(gendata.yres == 1200)
3113
 
        {
3114
 
                finalizeheader(1, LEFT);
3115
 
                gendata.ileave = 1;
3116
 
                encode_bw_buf();
3117
 
                lline++;
3118
 
        }
3119
 
 
3120
 
        /* And now load another buffer, starting to
3121
 
         * look for it from the first line after the 
3122
 
         * pass we have just done.
3123
 
         */
3124
 
        res = fill_mono_buffer(gendata.curvline + gendata.numblines);
3125
 
 
3126
 
        /* Now loop. Even this code is identical
3127
 
         * to the code above: the only difference
3128
 
         * is that here we also finalize the previous
3129
 
         * buffer before encoding this one. No need
3130
 
         * to check if the buffer is empty because
3131
 
         * a buffer is reported only if it's full
3132
 
         * or if it is the last one, so if it's not
3133
 
         * the last it must be full.
3134
 
         */
3135
 
        while(!(res & LAST))
3136
 
        {
3137
 
                calcbufmargins(LEFT);
3138
 
                finalizeheader(gendata.curvline - lline, LEFT);
3139
 
                gendata.ileave = 0;
3140
 
                encode_bw_buf();
3141
 
                lline = gendata.curvline;
3142
 
                if(gendata.yres == 1200)
3143
 
                {
3144
 
                        finalizeheader(1, LEFT);
3145
 
                        gendata.ileave = 1;
3146
 
                        encode_bw_buf();
3147
 
                        lline++;
3148
 
                }
3149
 
 
3150
 
                /* Get another buffer, and so on */
3151
 
                res = fill_mono_buffer(gendata.curvline + gendata.numblines);
3152
 
        }
3153
 
 
3154
 
        /* Last buffer. This can be either empty or full.
3155
 
         * If it's not empty (LHDATA bit set), print it.
3156
 
         */
3157
 
        if(res & LHDATA)
3158
 
        {
3159
 
                calcbufmargins(LEFT);
3160
 
                finalizeheader(gendata.curvline - lline, LEFT);
3161
 
                encode_bw_buf();        
3162
 
                if(gendata.yres == 1200)
3163
 
                {
3164
 
                        finalizeheader(1, LEFT);
3165
 
                        gendata.ileave = 1;
3166
 
                        encode_bw_buf();
3167
 
                        lline++;
3168
 
                }
3169
 
        }
3170
 
 
3171
 
        /* Finalize the last buffer */
3172
 
        finalizeheader(0, -1);
 
3081
{
 
3082
        int res, lline;
 
3083
 
 
3084
        /* Load the first buffer, skipping over
 
3085
         * blank lines (if any).
 
3086
         */
 
3087
        res = init_buffer();
 
3088
 
 
3089
        /* If we happen to have a buffer which is LAST
 
3090
         * and empty, we have a blank page to print:
 
3091
         * just say goodbye.
 
3092
         */
 
3093
        if(res == LAST)return;
 
3094
 
 
3095
        /* Skip enough lines to reach the start of
 
3096
         * the first stripe to print.
 
3097
         */
 
3098
        skiplines(gendata.curvline, BWTOPSTART);
 
3099
        lline = gendata.curvline;
 
3100
 
 
3101
        /* And now print the first buffer. This part of
 
3102
         * the code is identical to the LHDATA part in
 
3103
         * print_color_page()
 
3104
         */
 
3105
        calcbufmargins(LEFT);
 
3106
        gendata.ileave = 0;
 
3107
        encode_bw_buf();
 
3108
        lline = gendata.curvline;
 
3109
        if(gendata.yres == 1200)
 
3110
        {
 
3111
                finalizeheader(1, LEFT);
 
3112
                gendata.ileave = 1;
 
3113
                encode_bw_buf();
 
3114
                lline++;
 
3115
        }
 
3116
 
 
3117
        /* And now load another buffer, starting to
 
3118
         * look for it from the first line after the
 
3119
         * pass we have just done.
 
3120
         */
 
3121
        res = fill_mono_buffer(gendata.curvline + gendata.numblines);
 
3122
 
 
3123
        /* Now loop. Even this code is identical
 
3124
         * to the code above: the only difference
 
3125
         * is that here we also finalize the previous
 
3126
         * buffer before encoding this one. No need
 
3127
         * to check if the buffer is empty because
 
3128
         * a buffer is reported only if it's full
 
3129
         * or if it is the last one, so if it's not
 
3130
         * the last it must be full.
 
3131
         */
 
3132
        while(!(res & LAST))
 
3133
        {
 
3134
                calcbufmargins(LEFT);
 
3135
                finalizeheader(gendata.curvline - lline, LEFT);
 
3136
                gendata.ileave = 0;
 
3137
                encode_bw_buf();
 
3138
                lline = gendata.curvline;
 
3139
                if(gendata.yres == 1200)
 
3140
                {
 
3141
                        finalizeheader(1, LEFT);
 
3142
                        gendata.ileave = 1;
 
3143
                        encode_bw_buf();
 
3144
                        lline++;
 
3145
                }
 
3146
 
 
3147
                /* Get another buffer, and so on */
 
3148
                res = fill_mono_buffer(gendata.curvline + gendata.numblines);
 
3149
        }
 
3150
 
 
3151
        /* Last buffer. This can be either empty or full.
 
3152
         * If it's not empty (LHDATA bit set), print it.
 
3153
         */
 
3154
        if(res & LHDATA)
 
3155
        {
 
3156
                calcbufmargins(LEFT);
 
3157
                finalizeheader(gendata.curvline - lline, LEFT);
 
3158
                encode_bw_buf();
 
3159
                if(gendata.yres == 1200)
 
3160
                {
 
3161
                        finalizeheader(1, LEFT);
 
3162
                        gendata.ileave = 1;
 
3163
                        encode_bw_buf();
 
3164
                        lline++;
 
3165
                }
 
3166
        }
 
3167
 
 
3168
        /* Finalize the last buffer */
 
3169
        finalizeheader(0, -1);
3173
3170
}
3174
3171
 
3175
 
/* This is the equivalent of print_color_page() 
 
3172
/* This is the equivalent of print_color_page()
3176
3173
 * for photoquality output. They are almost identical,
3177
3174
 * the only real difference is that we now are
3178
3175
 * printing with two identical heads, so there is
3179
3176
 * no need to care for different heights of the
3180
3177
 * printing pens (i.e.: no "lastblack" tricks).
3181
 
 */ 
 
3178
 */
3182
3179
static void
3183
3180
print_photo_page(void)
3184
3181
{
3185
 
        int res, lline;
3186
 
 
3187
 
        res = init_buffer();
3188
 
        while(res == 0)res = roll_buffer();
3189
 
 
3190
 
        if(res == LAST)return;
3191
 
 
3192
 
        skiplines(gendata.curvline, COLTOPSTART);
3193
 
        lline = gendata.curvline;
3194
 
        
3195
 
        switch(res)
3196
 
        {
3197
 
                case LHDATA:
3198
 
                        calcbufmargins(LEFT);
3199
 
                        gendata.ileave = 0;
3200
 
                        encode_col_buf(LEFT);
3201
 
                        lline = gendata.curvline;
3202
 
                        if(gendata.yres == 1200)
3203
 
                        {
3204
 
                                finalizeheader(1, LEFT);
3205
 
                                gendata.ileave = 1;
3206
 
                                encode_col_buf(LEFT);
3207
 
                                lline++;
3208
 
                        }
3209
 
                        break;
3210
 
 
3211
 
                case RHDATA:
3212
 
                        calcbufmargins(RIGHT);
3213
 
                        gendata.ileave = 0;
3214
 
                        encode_col_buf(RIGHT);
3215
 
                        lline = gendata.curvline;
3216
 
                        if(gendata.yres == 1200)
3217
 
                        {
3218
 
                                finalizeheader(1, RIGHT);
3219
 
                                gendata.ileave = 1;
3220
 
                                encode_col_buf(RIGHT);
3221
 
                                lline++;
3222
 
                        }
3223
 
                        break;
3224
 
 
3225
 
                case LHDATA|RHDATA:
3226
 
                        calcbufmargins(LEFT);
3227
 
                        gendata.ileave = 0;
3228
 
                        encode_col_buf(LEFT);
3229
 
                        calcbufmargins(RIGHT);
3230
 
                        finalizeheader(0, RIGHT);
3231
 
                        encode_col_buf(RIGHT);
3232
 
                        lline = gendata.curvline;
3233
 
                        if(gendata.yres == 1200)
3234
 
                        {
3235
 
                                calcbufmargins(LEFT);
3236
 
                                finalizeheader(1, LEFT);
3237
 
                                gendata.ileave = 1;
3238
 
                                encode_col_buf(LEFT);
3239
 
                                calcbufmargins(RIGHT);
3240
 
                                finalizeheader(0, RIGHT);
3241
 
                                encode_col_buf(RIGHT);
3242
 
                                lline++;
3243
 
                        }
3244
 
 
3245
 
                        break;
3246
 
        }
3247
 
        
3248
 
        res = roll_buffer();
3249
 
 
3250
 
        while(!(res & LAST))
3251
 
        {
3252
 
                switch(res)
3253
 
                {
3254
 
                        case LHDATA:
3255
 
                                calcbufmargins(LEFT);
3256
 
                                finalizeheader(gendata.curvline - lline, LEFT);
3257
 
                                gendata.ileave = 0;
3258
 
                                encode_col_buf(LEFT);
3259
 
                                lline = gendata.curvline;
3260
 
                                if(gendata.yres == 1200)
3261
 
                                {
3262
 
                                        finalizeheader(1, LEFT);
3263
 
                                        gendata.ileave = 1;
3264
 
                                        encode_col_buf(LEFT);
3265
 
                                        lline++;
3266
 
                                }
3267
 
                                break;
3268
 
 
3269
 
                        case RHDATA:
3270
 
                                calcbufmargins(RIGHT);
3271
 
                                finalizeheader(gendata.curvline - lline, RIGHT);
3272
 
                                gendata.ileave = 0;
3273
 
                                encode_col_buf(RIGHT);
3274
 
                                lline = gendata.curvline;
3275
 
                                if(gendata.yres == 1200)
3276
 
                                {
3277
 
                                        finalizeheader(1, RIGHT);
3278
 
                                        gendata.ileave = 1;
3279
 
                                        encode_col_buf(RIGHT);
3280
 
                                        lline++;
3281
 
                                }
3282
 
                                break;
3283
 
                                
3284
 
                        case LHDATA|RHDATA:
3285
 
                                calcbufmargins(LEFT);
3286
 
                                finalizeheader(gendata.curvline - lline, LEFT);
3287
 
                                gendata.ileave = 0;
3288
 
                                encode_col_buf(LEFT);
3289
 
                                calcbufmargins(RIGHT);
3290
 
                                finalizeheader(0, RIGHT);
3291
 
                                encode_col_buf(RIGHT);
3292
 
                                lline = gendata.curvline;
3293
 
                                if(gendata.yres == 1200)
3294
 
                                {
3295
 
                                        calcbufmargins(LEFT);
3296
 
                                        finalizeheader(1, LEFT);
3297
 
                                        gendata.ileave = 1;
3298
 
                                        encode_col_buf(LEFT);
3299
 
                                        calcbufmargins(RIGHT);
3300
 
                                        finalizeheader(0, RIGHT);
3301
 
                                        encode_col_buf(RIGHT);
3302
 
                                        lline++;
3303
 
                                }
3304
 
                                break;
3305
 
                }
3306
 
                
3307
 
                res = roll_buffer();
3308
 
        }
3309
 
 
3310
 
        switch(res)
3311
 
        {
3312
 
                case LHDATA:
3313
 
                        calcbufmargins(LEFT);
3314
 
                        finalizeheader(gendata.curvline - lline, LEFT);
3315
 
                        gendata.ileave = 0;
3316
 
                        encode_col_buf(LEFT);
3317
 
                        if(gendata.yres == 1200)
3318
 
                        {
3319
 
                                finalizeheader(1, LEFT);
3320
 
                                gendata.ileave = 1;
3321
 
                                encode_col_buf(LEFT);
3322
 
                                lline++;
3323
 
                        }
3324
 
 
3325
 
                case RHDATA:
3326
 
                        calcbufmargins(RIGHT);
3327
 
                        finalizeheader(gendata.curvline - lline, RIGHT);
3328
 
                        gendata.ileave = 0;
3329
 
                        encode_col_buf(RIGHT);
3330
 
                        if(gendata.yres == 1200)
3331
 
                        {
3332
 
                                finalizeheader(1, RIGHT);
3333
 
                                gendata.ileave = 1;
3334
 
                                encode_col_buf(RIGHT);
3335
 
                                lline++;
3336
 
                        }
3337
 
                        break;
3338
 
                        
3339
 
                case LHDATA|RHDATA:
3340
 
                        calcbufmargins(LEFT);
3341
 
                        finalizeheader(gendata.curvline - lline, LEFT);
3342
 
                        gendata.ileave = 0;
3343
 
                        encode_col_buf(LEFT);
3344
 
                        calcbufmargins(RIGHT);
3345
 
                        finalizeheader(0, RIGHT);
3346
 
                        encode_col_buf(RIGHT);
3347
 
                        if(gendata.yres == 1200)
3348
 
                        {
3349
 
                                calcbufmargins(LEFT);
3350
 
                                finalizeheader(1, LEFT);
3351
 
                                gendata.ileave = 1;
3352
 
                                encode_col_buf(LEFT);
3353
 
                                calcbufmargins(RIGHT);
3354
 
                                finalizeheader(0, RIGHT);
3355
 
                                encode_col_buf(RIGHT);
3356
 
                                lline++;
3357
 
                        }
3358
 
                        break;
3359
 
        }
3360
 
 
3361
 
        finalizeheader(0, -1);
 
3182
        int res, lline;
 
3183
 
 
3184
        res = init_buffer();
 
3185
        while(res == 0)res = roll_buffer();
 
3186
 
 
3187
        if(res == LAST)return;
 
3188
 
 
3189
        skiplines(gendata.curvline, COLTOPSTART);
 
3190
        lline = gendata.curvline;
 
3191
 
 
3192
        switch(res)
 
3193
        {
 
3194
                case LHDATA:
 
3195
                        calcbufmargins(LEFT);
 
3196
                        gendata.ileave = 0;
 
3197
                        encode_col_buf(LEFT);
 
3198
                        lline = gendata.curvline;
 
3199
                        if(gendata.yres == 1200)
 
3200
                        {
 
3201
                                finalizeheader(1, LEFT);
 
3202
                                gendata.ileave = 1;
 
3203
                                encode_col_buf(LEFT);
 
3204
                                lline++;
 
3205
                        }
 
3206
                        break;
 
3207
 
 
3208
                case RHDATA:
 
3209
                        calcbufmargins(RIGHT);
 
3210
                        gendata.ileave = 0;
 
3211
                        encode_col_buf(RIGHT);
 
3212
                        lline = gendata.curvline;
 
3213
                        if(gendata.yres == 1200)
 
3214
                        {
 
3215
                                finalizeheader(1, RIGHT);
 
3216
                                gendata.ileave = 1;
 
3217
                                encode_col_buf(RIGHT);
 
3218
                                lline++;
 
3219
                        }
 
3220
                        break;
 
3221
 
 
3222
                case LHDATA|RHDATA:
 
3223
                        calcbufmargins(LEFT);
 
3224
                        gendata.ileave = 0;
 
3225
                        encode_col_buf(LEFT);
 
3226
                        calcbufmargins(RIGHT);
 
3227
                        finalizeheader(0, RIGHT);
 
3228
                        encode_col_buf(RIGHT);
 
3229
                        lline = gendata.curvline;
 
3230
                        if(gendata.yres == 1200)
 
3231
                        {
 
3232
                                calcbufmargins(LEFT);
 
3233
                                finalizeheader(1, LEFT);
 
3234
                                gendata.ileave = 1;
 
3235
                                encode_col_buf(LEFT);
 
3236
                                calcbufmargins(RIGHT);
 
3237
                                finalizeheader(0, RIGHT);
 
3238
                                encode_col_buf(RIGHT);
 
3239
                                lline++;
 
3240
                        }
 
3241
 
 
3242
                        break;
 
3243
        }
 
3244
 
 
3245
        res = roll_buffer();
 
3246
 
 
3247
        while(!(res & LAST))
 
3248
        {
 
3249
                switch(res)
 
3250
                {
 
3251
                        case LHDATA:
 
3252
                                calcbufmargins(LEFT);
 
3253
                                finalizeheader(gendata.curvline - lline, LEFT);
 
3254
                                gendata.ileave = 0;
 
3255
                                encode_col_buf(LEFT);
 
3256
                                lline = gendata.curvline;
 
3257
                                if(gendata.yres == 1200)
 
3258
                                {
 
3259
                                        finalizeheader(1, LEFT);
 
3260
                                        gendata.ileave = 1;
 
3261
                                        encode_col_buf(LEFT);
 
3262
                                        lline++;
 
3263
                                }
 
3264
                                break;
 
3265
 
 
3266
                        case RHDATA:
 
3267
                                calcbufmargins(RIGHT);
 
3268
                                finalizeheader(gendata.curvline - lline, RIGHT);
 
3269
                                gendata.ileave = 0;
 
3270
                                encode_col_buf(RIGHT);
 
3271
                                lline = gendata.curvline;
 
3272
                                if(gendata.yres == 1200)
 
3273
                                {
 
3274
                                        finalizeheader(1, RIGHT);
 
3275
                                        gendata.ileave = 1;
 
3276
                                        encode_col_buf(RIGHT);
 
3277
                                        lline++;
 
3278
                                }
 
3279
                                break;
 
3280
 
 
3281
                        case LHDATA|RHDATA:
 
3282
                                calcbufmargins(LEFT);
 
3283
                                finalizeheader(gendata.curvline - lline, LEFT);
 
3284
                                gendata.ileave = 0;
 
3285
                                encode_col_buf(LEFT);
 
3286
                                calcbufmargins(RIGHT);
 
3287
                                finalizeheader(0, RIGHT);
 
3288
                                encode_col_buf(RIGHT);
 
3289
                                lline = gendata.curvline;
 
3290
                                if(gendata.yres == 1200)
 
3291
                                {
 
3292
                                        calcbufmargins(LEFT);
 
3293
                                        finalizeheader(1, LEFT);
 
3294
                                        gendata.ileave = 1;
 
3295
                                        encode_col_buf(LEFT);
 
3296
                                        calcbufmargins(RIGHT);
 
3297
                                        finalizeheader(0, RIGHT);
 
3298
                                        encode_col_buf(RIGHT);
 
3299
                                        lline++;
 
3300
                                }
 
3301
                                break;
 
3302
                }
 
3303
 
 
3304
                res = roll_buffer();
 
3305
        }
 
3306
 
 
3307
        switch(res)
 
3308
        {
 
3309
                case LHDATA:
 
3310
                        calcbufmargins(LEFT);
 
3311
                        finalizeheader(gendata.curvline - lline, LEFT);
 
3312
                        gendata.ileave = 0;
 
3313
                        encode_col_buf(LEFT);
 
3314
                        if(gendata.yres == 1200)
 
3315
                        {
 
3316
                                finalizeheader(1, LEFT);
 
3317
                                gendata.ileave = 1;
 
3318
                                encode_col_buf(LEFT);
 
3319
                                lline++;
 
3320
                        }
 
3321
 
 
3322
                case RHDATA:
 
3323
                        calcbufmargins(RIGHT);
 
3324
                        finalizeheader(gendata.curvline - lline, RIGHT);
 
3325
                        gendata.ileave = 0;
 
3326
                        encode_col_buf(RIGHT);
 
3327
                        if(gendata.yres == 1200)
 
3328
                        {
 
3329
                                finalizeheader(1, RIGHT);
 
3330
                                gendata.ileave = 1;
 
3331
                                encode_col_buf(RIGHT);
 
3332
                                lline++;
 
3333
                        }
 
3334
                        break;
 
3335
 
 
3336
                case LHDATA|RHDATA:
 
3337
                        calcbufmargins(LEFT);
 
3338
                        finalizeheader(gendata.curvline - lline, LEFT);
 
3339
                        gendata.ileave = 0;
 
3340
                        encode_col_buf(LEFT);
 
3341
                        calcbufmargins(RIGHT);
 
3342
                        finalizeheader(0, RIGHT);
 
3343
                        encode_col_buf(RIGHT);
 
3344
                        if(gendata.yres == 1200)
 
3345
                        {
 
3346
                                calcbufmargins(LEFT);
 
3347
                                finalizeheader(1, LEFT);
 
3348
                                gendata.ileave = 1;
 
3349
                                encode_col_buf(LEFT);
 
3350
                                calcbufmargins(RIGHT);
 
3351
                                finalizeheader(0, RIGHT);
 
3352
                                encode_col_buf(RIGHT);
 
3353
                                lline++;
 
3354
                        }
 
3355
                        break;
 
3356
        }
 
3357
 
 
3358
        finalizeheader(0, -1);
3362
3359
}