~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to src/gdevclj.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
 
   All Rights Reserved.
3
 
  
4
 
   This software is provided AS-IS with no warranty, either express or
5
 
   implied.
6
 
 
7
 
   This software is distributed under license and may not be copied, modified
8
 
   or distributed except as expressly authorized under the terms of that
9
 
   license.  Refer to licensing information at http://www.artifex.com/
10
 
   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11
 
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
 
*/
13
 
/* $Id: gdevclj.c 8250 2007-09-25 13:31:24Z giles $ */
14
 
/*
15
 
 * H-P Color LaserJet 5/5M device; based on the PaintJet.
16
 
 */
17
 
#include "math_.h"
18
 
#include "gx.h"
19
 
#include "gsparam.h"
20
 
#include "gdevprn.h"
21
 
#include "gdevpcl.h"
22
 
 
23
 
typedef struct gx_device_clj_s gx_device_clj;
24
 
struct gx_device_clj_s {
25
 
        gx_device_common;
26
 
        gx_prn_device_common;
27
 
        bool rotated;
28
 
};
29
 
 
30
 
#define pclj ((gx_device_clj *)pdev)
31
 
 
32
 
/*
33
 
 * The HP Color LaserJet 5/5M provides a rather unexpected speed/performance
34
 
 * tradeoff.
35
 
 *
36
 
 * When generating rasters, only the fixed (simple) color spaces provide
37
 
 * reasonable performance (in this case, reasonable != good). However, in
38
 
 * these modes, certain of the fully-saturated primary colors (cyan, blue,
39
 
 * green, and red) are rendered differently as rasters as opposed to colored
40
 
 * geometric objects. Hence, the color of the output will be other than what
41
 
 * is expected.
42
 
 *
43
 
 * Alternatively, the direct color, 1-bit per pixel scheme can be used. This
44
 
 * will produce the expected colors, but performance will deteriorate
45
 
 * significantly (observed printing time will be about 3 times longer than
46
 
 * when using the simple color mode).
47
 
 *
48
 
 * Note that when using the latter mode to view output from the PCL
49
 
 * interpreter, geometric objects and raster rendered with other than
50
 
 * geometric color spaces will have the same appearance as if sent directly
51
 
 * to the CLJ, but rasters generated from simple color spaces will have a
52
 
 * different appearance. To make the latter rasters match in appearance, the
53
 
 * faster printing mode must be used (in which the case the other objects
54
 
 * will not have the same appearance).
55
 
 */
56
 
#define USE_FAST_MODE
57
 
 
58
 
/* X_DPI and Y_DPI must be the same */
59
 
#define X_DPI 300
60
 
#define Y_DPI 300
61
 
 
62
 
/*
63
 
 * Array of paper sizes, and the corresponding offsets.
64
 
 */
65
 
typedef struct clj_paper_size_s {
66
 
    uint        tag;                /* paper type tag */
67
 
    int         orient;             /* logical page orientation to use */
68
 
    float       width, height;      /* in pts; +- 5 pts */
69
 
    gs_point    offsets;            /* offsets in the given orientation */
70
 
} clj_paper_size;
71
 
 
72
 
/*
73
 
 * The Color LaserJet prints page sizes up to 11.8" wide (A4 size) in
74
 
 * long-edge-feed (landscape) orientation. Only executive, letter, and
75
 
 * A4 size are supported for color, so we don't bother to list the others.
76
 
 */
77
 
static const clj_paper_size    clj_paper_sizes[] = {
78
 
    /* U.S. letter size comes first so it will be the default. */
79
 
    {   2,  1, 11.00 * 72.0, 8.50 * 72.0, { .200 * 72.0, 0.0 } },
80
 
    {   1,  1, 10.50 * 72.0, 7.25 * 72.0, { .200 * 72.0, 0.0 } },
81
 
    {  26,  1, 11.69 * 72.0, 8.27 * 72.0, { .197 * 72.0, 0.0 } }
82
 
};
83
 
 
84
 
/*
85
 
 * The supported set of resolutions.
86
 
 *
87
 
 * The Color LaserJet 5/5M is actually a pseudo-contone device, with hardware
88
 
 * capable of providing about 16 levels of intensity. The current code does
89
 
 * not take advantage of this feature, because it is not readily controllable
90
 
 * via PCL. Rather, the device is modeled as a bi-level device in each of
91
 
 * three color planes. The maximum supported resolution for such an arrangement
92
 
 * is 300 dpi.
93
 
 *
94
 
 * The CLJ does support raster scaling, but to invoke that scaling, even for
95
 
 * integral factors, involves a large performance penalty. Hence, only those
96
 
 * resolutions that can be supported without invoking raster scaling are
97
 
 * included here. These resolutions are always the same in the fast and slow
98
 
 * scan directions, so only a single value is listed here.
99
 
 *
100
 
 * All valuse are in dots per inch.
101
 
 */
102
 
static const float supported_resolutions[] = { 75.0, 100.0, 150.0, 300.0 };
103
 
 
104
 
 
105
 
/* indicate the maximum supported resolution and scan-line length (pts) */
106
 
#define CLJ_MAX_RES        300.0
107
 
#define CLJ_MAX_SCANLINE   (12.0 * 72.0)
108
 
 
109
 
 
110
 
/*
111
 
 * Determine a requested resolution pair is supported.
112
 
 */
113
 
  static bool
114
 
is_supported_resolution(
115
 
    const float HWResolution[2]
116
 
)
117
 
{
118
 
    int     i;
119
 
 
120
 
    for (i = 0; i < countof(supported_resolutions); i++) {
121
 
        if (HWResolution[0] == supported_resolutions[i])
122
 
            return HWResolution[0] == HWResolution[1];
123
 
    }
124
 
    return false;
125
 
}
126
 
 
127
 
/* ---------------- Standard driver ---------------- */
128
 
 
129
 
/*
130
 
 * Find the paper size information corresponding to a given pair of dimensions.
131
 
 * If rotatep != 0, *rotatep is set to true if the page must be rotated 90
132
 
 * degrees to fit.
133
 
 *
134
 
 * A return value of 0 indicates the paper size is not supported.
135
 
 *
136
 
 * Note that for the standard driver, rotation is not allowed.
137
 
 */
138
 
  static const clj_paper_size *
139
 
get_paper_size(
140
 
    const float             MediaSize[2],
141
 
    bool *                  rotatep
142
 
)
143
 
{
144
 
    static const float      tolerance = 5.0;
145
 
    float                   width = MediaSize[0];
146
 
    float                   height = MediaSize[1];
147
 
    const clj_paper_size *  psize = 0;
148
 
    int                     i;
149
 
 
150
 
    for (i = 0, psize = clj_paper_sizes; i < countof(clj_paper_sizes); i++, psize++) {
151
 
        if ( (fabs(width - psize->width) <= tolerance)  &&
152
 
             (fabs(height - psize->height) <= tolerance)  ) {
153
 
            if (rotatep != 0)
154
 
                *rotatep = false;
155
 
            return psize;
156
 
        } else if ( (fabs(width - psize->height) <= tolerance) &&
157
 
                    (fabs(height - psize->width) <= tolerance)   ) {
158
 
            if (rotatep != 0)
159
 
                *rotatep = true;
160
 
            return psize;
161
 
        }
162
 
    }
163
 
 
164
 
    return 0;
165
 
}
166
 
 
167
 
/*
168
 
 * Get the (PostScript style) default matrix for the current page size.
169
 
 *
170
 
 * For all of the supported sizes, the page will be printed with long-edge
171
 
 * feed (the CLJ does support some additional sizes, but only for monochrome).
172
 
 * As will all HP laser printers, the printable region marin is 12 pts. from
173
 
 * the edge of the physical page.
174
 
 */
175
 
static void
176
 
clj_get_initial_matrix( gx_device *pdev, gs_matrix *pmat)
177
 
{
178
 
    floatp              fs_res = pdev->HWResolution[0] / 72.0;
179
 
    floatp              ss_res = pdev->HWResolution[1] / 72.0;
180
 
    const clj_paper_size *psize;
181
 
 
182
 
    psize = get_paper_size(pdev->MediaSize, NULL);
183
 
    /* if the paper size is not recognized, not much can be done */
184
 
    /* This shouldn't be possible since clj_put_params rejects   */
185
 
    /* unknown media sizes.                                      */
186
 
    if (psize == 0) {
187
 
        pmat->xx = fs_res;
188
 
        pmat->xy = 0.0;
189
 
        pmat->yx = 0.0;
190
 
        pmat->yy = -ss_res;
191
 
        pmat->tx = 0.0;
192
 
        pmat->ty = pdev->MediaSize[1] * ss_res;
193
 
        return;
194
 
    }
195
 
  
196
 
    if (pclj->rotated) {
197
 
        pmat->xx = 0.0;
198
 
        pmat->xy = ss_res;
199
 
        pmat->yx = fs_res;
200
 
        pmat->yy = 0.0;
201
 
        pmat->tx = -psize->offsets.x * fs_res;
202
 
        pmat->ty = -psize->offsets.y * ss_res;
203
 
    } else {
204
 
        pmat->xx = fs_res;
205
 
        pmat->xy = 0.0;
206
 
        pmat->yx = 0.0;
207
 
        pmat->yy = -ss_res;
208
 
        pmat->tx = -psize->offsets.x * fs_res;
209
 
        pmat->ty = pdev->height + psize->offsets.y * ss_res;
210
 
    }
211
 
}
212
 
 
213
 
/*
214
 
 * Get parameters, including InputAttributes for all supported page sizes.
215
 
 * We associate each page size with a different "media source", since that
216
 
 * is currently the only way to register multiple page sizes.
217
 
 */
218
 
static int
219
 
clj_get_params(gx_device *pdev, gs_param_list *plist)
220
 
{
221
 
    gs_param_dict mdict;
222
 
    int code = gdev_prn_get_params(pdev, plist);
223
 
    int ecode = code;
224
 
    int i;
225
 
 
226
 
    code = gdev_begin_input_media(plist, &mdict, countof(clj_paper_sizes));
227
 
    if (code < 0)
228
 
        ecode = code;
229
 
    else {
230
 
        for (i = 0; i < countof(clj_paper_sizes); ++i) {
231
 
            code = gdev_write_input_page_size(i, &mdict,
232
 
                                              clj_paper_sizes[i].width,
233
 
                                              clj_paper_sizes[i].height);
234
 
            if (code < 0)
235
 
                ecode = code;
236
 
        }
237
 
        code = gdev_end_input_media(plist, &mdict);
238
 
        if (code < 0)
239
 
            ecode = code;
240
 
    }
241
 
    return ecode;
242
 
}
243
 
 
244
 
/*
245
 
 * Get the media size being set by put_params, if any.  Return 0 if no media
246
 
 * size is being set, 1 (and set mediasize[]) if the size is being set, <0
247
 
 * on error.
248
 
 */
249
 
static int
250
 
clj_media_size(float mediasize[2], gs_param_list *plist)
251
 
{
252
 
    gs_param_float_array fres;
253
 
    gs_param_float_array fsize;
254
 
    gs_param_int_array hwsize;
255
 
    int have_pagesize = 0;
256
 
 
257
 
    if ( (param_read_float_array(plist, "HWResolution", &fres) == 0) &&
258
 
          !is_supported_resolution(fres.data) ) 
259
 
        return_error(gs_error_rangecheck);
260
 
 
261
 
    if ( (param_read_float_array(plist, "PageSize", &fsize) == 0) ||
262
 
         (param_read_float_array(plist, ".MediaSize", &fsize) == 0) ) {
263
 
        mediasize[0] = fsize.data[0];
264
 
        mediasize[1] = fsize.data[1];
265
 
        have_pagesize = 1;
266
 
    }
267
 
 
268
 
    if (param_read_int_array(plist, "HWSize", &hwsize) == 0) {
269
 
        mediasize[0] = ((float)hwsize.data[0]) / fres.data[0];
270
 
        mediasize[1] = ((float)hwsize.data[1]) / fres.data[1];
271
 
        have_pagesize = 1;
272
 
    }
273
 
 
274
 
    return have_pagesize;
275
 
}
276
 
 
277
 
/*
278
 
 * Special put_params routine, to make certain the desired MediaSize and
279
 
 * HWResolution are supported.
280
 
 */
281
 
  static int
282
 
clj_put_params(
283
 
    gx_device *             pdev,
284
 
    gs_param_list *         plist
285
 
)
286
 
{
287
 
    float                   mediasize[2];
288
 
    bool                    rotate = false;
289
 
    int                     have_pagesize = clj_media_size(mediasize, plist);
290
 
 
291
 
    if (have_pagesize < 0)
292
 
        return have_pagesize;
293
 
    if (have_pagesize) {
294
 
        if (get_paper_size(mediasize, &rotate) == 0 || rotate)
295
 
            return_error(gs_error_rangecheck);
296
 
    }
297
 
    return gdev_prn_put_params(pdev, plist);
298
 
}
299
 
 
300
 
/*
301
 
 * Pack and then compress a scanline of data. Return the size of the compressed
302
 
 * data produced.
303
 
 *
304
 
 * Input is arranged with one byte per pixel, but only the three low-order bits
305
 
 * are used. These bits are in order ymc, with yellow being the highest order
306
 
 * bit.
307
 
 *
308
 
 * Output is arranged in three planes, with one bit per pixel per plane. The
309
 
 * Color LaserJet 5/5M does support more congenial pixel encodings, but use
310
 
 * of anything other than the fixed palettes seems to result in very poor
311
 
 * performance.
312
 
 *
313
 
 * Only compresion mode 2 is used. Compression mode 1 (pure run length) has
314
 
 * an advantage over compression mode 2 only in cases in which very long runs
315
 
 * occur (> 128 bytes). Since both methods provide good compression in that
316
 
 * case, it is not worth worrying about, and compression mode 2 provides much
317
 
 * better worst-case behavior. Compression mode 3 requires considerably more
318
 
 * effort to generate, so it is useful only when it is known a prior that
319
 
 * scanlines repeat frequently.
320
 
 */
321
 
  static void
322
 
pack_and_compress_scanline(
323
 
    const byte *        pin,
324
 
    int                 in_size,
325
 
    byte  *             pout[3],
326
 
    int                 out_size[3]
327
 
)
328
 
{
329
 
#define BUFF_SIZE                                                           \
330
 
    ( ((int)(CLJ_MAX_RES * CLJ_MAX_SCANLINE / 72.0) + sizeof(ulong) - 1)    \
331
 
         / sizeof(ulong) )
332
 
 
333
 
    ulong               buff[3 * BUFF_SIZE];
334
 
    byte *              p_c = (byte *)buff;
335
 
    byte *              p_m = (byte *)(buff + BUFF_SIZE);
336
 
    byte *              p_y = (byte *)(buff + 2 * BUFF_SIZE);
337
 
    ulong *             ptrs[3];
338
 
    byte                c_val = 0, m_val = 0, y_val = 0;
339
 
    ulong               mask = 0x80;
340
 
    int                 i;
341
 
 
342
 
    /* pack the input for 4-bits per index */
343
 
    for (i = 0; i < in_size; i++) {
344
 
        uint    ival = *pin++;
345
 
 
346
 
        if (ival != 0) {
347
 
            if ((ival & 0x4) != 0)
348
 
                y_val |= mask;
349
 
            if ((ival & 0x2) != 0)
350
 
                m_val |= mask;
351
 
            if ((ival & 0x1) != 0)
352
 
                c_val |= mask;
353
 
        }
354
 
 
355
 
        if ((mask >>= 1) == 0) {
356
 
            /* NB - write out in byte units */
357
 
            *p_c++ = c_val;
358
 
            c_val = 0L;
359
 
            *p_m++ = m_val;
360
 
            m_val = 0L;
361
 
            *p_y++ = y_val;
362
 
            y_val = 0L;
363
 
            mask = 0x80;
364
 
        }
365
 
    }
366
 
    if (mask != 0x80) {
367
 
        /* NB - write out in byte units */
368
 
        *p_c++ = c_val;
369
 
        *p_m++ = m_val;
370
 
        *p_y++ = y_val;
371
 
    }
372
 
 
373
 
    /* clear to up a longword boundary */
374
 
    while ((((ulong)p_c) & (sizeof(ulong) - 1)) != 0) {
375
 
        *p_c++ = 0;
376
 
        *p_m++ = 0;
377
 
        *p_y++ = 0;
378
 
    }
379
 
 
380
 
    ptrs[0] = (ulong *)p_c;
381
 
    ptrs[1] = (ulong *)p_m;
382
 
    ptrs[2] = (ulong *)p_y;
383
 
 
384
 
    for (i = 0; i < 3; i++) {
385
 
        ulong * p_start = buff + i * BUFF_SIZE;
386
 
        ulong * p_end = ptrs[i];
387
 
 
388
 
        /* eleminate trailing 0's */
389
 
        while ((p_end > p_start) && (p_end[-1] == 0))
390
 
            p_end--;
391
 
 
392
 
        if (p_start == p_end)
393
 
            out_size[i] = 0;
394
 
        else
395
 
            out_size[i] = gdev_pcl_mode2compress(p_start, p_end, pout[i]);
396
 
    }
397
 
 
398
 
#undef BUFF_SIZE
399
 
}
400
 
 
401
 
/*
402
 
 * Send the page to the printer.  Compress each scan line.
403
 
 */
404
 
  static int
405
 
clj_print_page(
406
 
    gx_device_printer *     pdev,
407
 
    FILE *                  prn_stream
408
 
)
409
 
{
410
 
    gs_memory_t *mem = pdev->memory;
411
 
    bool                    rotate;
412
 
    const clj_paper_size *  psize = get_paper_size(pdev->MediaSize, &rotate);
413
 
    int                     lsize = pdev->width;
414
 
    int                     clsize = (lsize + (lsize + 255) / 128) / 8;
415
 
    byte *                  data = 0;
416
 
    byte *                  cdata[3];
417
 
    int                     blank_lines = 0;
418
 
    int                     i;
419
 
    floatp                  fs_res = pdev->HWResolution[0] / 72.0;
420
 
    floatp                  ss_res = pdev->HWResolution[1] / 72.0;
421
 
    int                     imageable_width, imageable_height;
422
 
 
423
 
    /* no paper size at this point is a serious error */
424
 
    if (psize == 0)
425
 
        return_error(gs_error_unregistered);
426
 
 
427
 
    /* allocate memory for the raw and compressed data */
428
 
    if ((data = gs_alloc_bytes(mem, lsize, "clj_print_page(data)")) == 0)
429
 
        return_error(gs_error_VMerror);
430
 
    if ((cdata[0] = gs_alloc_bytes(mem, 3 * clsize, "clj_print_page(cdata)")) == 0) {
431
 
        gs_free_object(mem, data, "clj_print_page(data)");
432
 
        return_error(gs_error_VMerror);
433
 
    }
434
 
    cdata[1] = cdata[0] + clsize;
435
 
    cdata[2] = cdata[1] + clsize;
436
 
 
437
 
 
438
 
    /* Imageable area is without the margins. Note that the actual rotation
439
 
     * of page size into pdev->width & height has been done. We just use
440
 
     * rotate to access the correct offsets. */
441
 
    if (pclj->rotated) {
442
 
        imageable_width = pdev->width - (2 * psize->offsets.x) * fs_res;
443
 
        imageable_height = pdev->height - (2 * psize->offsets.y) * ss_res;
444
 
    }
445
 
    else {
446
 
        imageable_width = pdev->width - (2 * psize->offsets.y) * ss_res;
447
 
        imageable_height = pdev->height - (2 * psize->offsets.x) * fs_res;
448
 
    }
449
 
 
450
 
    /* start the page.  The pcl origin (0, 150 dots by default, y
451
 
       increasing down the long edge side of the page) needs to be
452
 
       offset such that it coincides with the offsets of the imageable
453
 
       area.  This calculation should be independant of rotation but
454
 
       only the rotated case has been tested with a real device. */
455
 
    fprintf( prn_stream,
456
 
             "\033E\033&u300D\033&l%da1x%dO\033*p0x0y+50x-100Y\033*t%dR"
457
 
#ifdef USE_FAST_MODE
458
 
             "\033*r-3U"
459
 
#else
460
 
             "\033*v6W\001\002\003\001\001\001"
461
 
#endif
462
 
             "\033*r0f%ds%dt1A\033*b2M",
463
 
             psize->tag,
464
 
             pclj->rotated,
465
 
             (int)(pdev->HWResolution[0]),
466
 
             imageable_width,
467
 
             imageable_height
468
 
             );
469
 
 
470
 
    /* process each scanline */
471
 
    for (i = 0; i < imageable_height; i++) {
472
 
        int     clen[3];
473
 
 
474
 
        gdev_prn_copy_scan_lines(pdev, i, data, lsize);
475
 
 
476
 
        /* The 'lsize' bytes of data have the blank margin area at the end due  */
477
 
        /* to the 'initial_matrix' offsets that are applied.                    */
478
 
        pack_and_compress_scanline(data, imageable_width, cdata, clen);
479
 
        if ((clen[0] == 0) && (clen[1] == 0) && (clen[2] == 0))
480
 
            ++blank_lines;
481
 
        else {
482
 
            if (blank_lines != 0) {
483
 
                fprintf(prn_stream, "\033*b%dY", blank_lines);
484
 
                blank_lines = 0;
485
 
            }
486
 
            fprintf(prn_stream, "\033*b%dV", clen[0]);
487
 
            fwrite(cdata[0], sizeof(byte), clen[0], prn_stream);
488
 
            fprintf(prn_stream, "\033*b%dV", clen[1]);
489
 
            fwrite(cdata[1], sizeof(byte), clen[1], prn_stream);
490
 
            fprintf(prn_stream, "\033*b%dW", clen[2]);
491
 
            fwrite(cdata[2], sizeof(byte), clen[2], prn_stream);
492
 
        }
493
 
    }
494
 
 
495
 
    /* PCL will take care of blank lines at the end */
496
 
    fputs("\033*rC\f", prn_stream);
497
 
 
498
 
    /* free the buffers used */
499
 
    gs_free_object(mem, cdata[0], "clj_print_page(cdata)");
500
 
    gs_free_object(mem, data, "clj_print_page(data)");
501
 
 
502
 
    return 0;
503
 
}
504
 
 
505
 
/* CLJ device methods */
506
 
#define CLJ_PROCS(get_params, put_params)\
507
 
    gdev_prn_open,                  /* open_device */\
508
 
    clj_get_initial_matrix,         /* get_initial matrix */\
509
 
    NULL,                           /* sync_output */\
510
 
    gdev_prn_output_page,           /* output_page */\
511
 
    gdev_prn_close,                 /* close_device */\
512
 
    gdev_pcl_3bit_map_rgb_color,    /* map_rgb_color */\
513
 
    gdev_pcl_3bit_map_color_rgb,    /* map_color_rgb */\
514
 
    NULL,                           /* fill_rectangle */\
515
 
    NULL,                           /* tile_rectangle */\
516
 
    NULL,                           /* copy_mono */\
517
 
    NULL,                           /* copy_color */\
518
 
    NULL,                           /* obsolete draw_line */\
519
 
    NULL,                           /* get_bits */\
520
 
    get_params,                     /* get_params */\
521
 
    put_params,                     /* put_params */\
522
 
    NULL,                           /* map_cmyk_color */\
523
 
    NULL,                           /* get_xfont_procs */\
524
 
    NULL,                           /* get_xfont_device */\
525
 
    NULL,                           /* map_rgb_alpha_color */\
526
 
    gx_page_device_get_page_device  /* get_page_device */
527
 
 
528
 
static gx_device_procs cljet5_procs = {
529
 
    CLJ_PROCS(clj_get_params, clj_put_params)
530
 
};
531
 
 
532
 
/* CLJ device structure */
533
 
#define CLJ_DEVICE_BODY(procs, dname, rotated)\
534
 
  prn_device_body(\
535
 
    gx_device_clj,\
536
 
    procs,                  /* procedures */\
537
 
    dname,                  /* device name */\
538
 
    110,                    /* width - will be overridden subsequently */\
539
 
    85,                     /* height - will be overridden subsequently */\
540
 
    X_DPI, Y_DPI,           /* resolutions - current must be the same */\
541
 
    0.167, 0.167,           /* margins (left, bottom, right, top */\
542
 
    0.167, 0.167,\
543
 
    3,                      /* num_components - 3 colors, 1 bit per pixel */\
544
 
    8,                      /* depth - pack into bytes */\
545
 
    1, 1,                   /* max_gray=max_component=1 */\
546
 
    2, 2,                   /* dithered_grays=dithered_components=2 */ \
547
 
    clj_print_page          /* routine to output page */\
548
 
),\
549
 
    rotated                 /* rotated - may be overridden subsequently */
550
 
 
551
 
gx_device_clj gs_cljet5_device = {
552
 
    CLJ_DEVICE_BODY(cljet5_procs, "cljet5", 0 /*false*/)
553
 
};
554
 
 
555
 
/* ---------------- Driver with page rotation ---------------- */
556
 
 
557
 
/*
558
 
 * For use with certain PCL interpreters, which don't implement
559
 
 * setpagedevice, we provide a version of this driver that attempts to
560
 
 * handle page rotation at the driver level.  This version breaks an
561
 
 * invariant that all drivers must obey, namely, that drivers are not
562
 
 * allowed to change the parameters passed by put_params (they can only
563
 
 * accept or reject them).  Consequently, this driver must not be used in
564
 
 * any context other than these specific PCL interpreters.  We support this
565
 
 * hack only because these PCL interpreters can't be changed to handle page
566
 
 * rotation properly.
567
 
 */
568
 
 
569
 
/*
570
 
 * Special get_params routine, to fake MediaSize, width, and height if
571
 
 * we were in a 'rotated' state.
572
 
 */
573
 
static int
574
 
clj_pr_get_params( gx_device *pdev, gs_param_list *plist )
575
 
{
576
 
    int code;
577
 
 
578
 
    /* First un-rotate the MediaSize, etc. if we were in a rotated mode         */
579
 
    if (pclj->rotated) {
580
 
        float ftmp;
581
 
        int   itmp;
582
 
 
583
 
        ftmp = pdev->MediaSize[0];
584
 
        pdev->MediaSize[0] = pdev->MediaSize[1];
585
 
        pdev->MediaSize[1] = ftmp;
586
 
        itmp = pdev->width;
587
 
        pdev->width = pdev->height;
588
 
        pdev->height = itmp;
589
 
    }
590
 
 
591
 
    /* process the parameter list */
592
 
    code = gdev_prn_get_params(pdev, plist);
593
 
 
594
 
    /* Now re-rotate the page size if needed */
595
 
    if (pclj->rotated) {
596
 
        float ftmp;
597
 
        int   itmp;
598
 
 
599
 
        ftmp = pdev->MediaSize[0];
600
 
        pdev->MediaSize[0] = pdev->MediaSize[1];
601
 
        pdev->MediaSize[1] = ftmp;
602
 
        itmp = pdev->width;
603
 
        pdev->width = pdev->height;
604
 
        pdev->height = itmp;
605
 
    }
606
 
 
607
 
    return code;
608
 
}
609
 
 
610
 
/*
611
 
 * Special put_params routine, to intercept changes in the MediaSize, and to
612
 
 * make certain the desired MediaSize and HWResolution are supported.
613
 
 *
614
 
 * This function will rotate MediaSize if it is needed by the device in
615
 
 * order to print this size page.
616
 
 */
617
 
  static int
618
 
clj_pr_put_params(
619
 
    gx_device *             pdev,
620
 
    gs_param_list *         plist
621
 
)
622
 
{
623
 
    float                   mediasize[2];
624
 
    int                     code = 0;
625
 
    bool                    rotate = false;
626
 
    int                     have_pagesize = clj_media_size(mediasize, plist);
627
 
 
628
 
    if (have_pagesize < 0)
629
 
        return have_pagesize;
630
 
    if (have_pagesize) {
631
 
        if (get_paper_size(mediasize, &rotate) == 0)
632
 
            return_error(gs_error_rangecheck);
633
 
        if (rotate) {
634
 
            /* We need to rotate the requested page size, so synthesize a new   */
635
 
            /* parameter list in front of the requestor's list to force the     */
636
 
            /* rotated page size.                                               */
637
 
            gs_param_float_array        pf_array;
638
 
            gs_c_param_list             alist;
639
 
            float                       ftmp = mediasize[0];
640
 
 
641
 
            mediasize[0] = mediasize[1];
642
 
            mediasize[1] = ftmp;
643
 
            pf_array.data = mediasize;
644
 
            pf_array.size = 2;
645
 
            pf_array.persistent = false;
646
 
 
647
 
            gs_c_param_list_write(&alist, pdev->memory);
648
 
            code = param_write_float_array((gs_param_list *)&alist, ".MediaSize", &pf_array);
649
 
            gs_c_param_list_read(&alist);
650
 
 
651
 
            /* stick this synthesized parameter on the front of the existing list */
652
 
            gs_c_param_list_set_target(&alist, plist);
653
 
            if ((code = gdev_prn_put_params(pdev, (gs_param_list *)&alist)) >= 0)
654
 
                pclj->rotated = true;
655
 
            gs_c_param_list_release(&alist);
656
 
        } else {
657
 
            if ((code = gdev_prn_put_params(pdev, plist)) >= 0)
658
 
                pclj->rotated = false;
659
 
        }
660
 
    } else 
661
 
        code = gdev_prn_put_params(pdev, plist);
662
 
 
663
 
    return code;
664
 
}
665
 
 
666
 
/* CLJ device methods -- se above for CLJ_PROCS */
667
 
static gx_device_procs cljet5pr_procs = {
668
 
    CLJ_PROCS(clj_pr_get_params, clj_pr_put_params)
669
 
};
670
 
 
671
 
/* CLJ device structure -- see above for CLJ_DEVICE_BODY */
672
 
gx_device_clj gs_cljet5pr_device = {
673
 
    CLJ_DEVICE_BODY(cljet5pr_procs, "cljet5pr", 1 /*true*/)
674
 
};