Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gdevdjtc.c,v 1.6 2002/06/16 05:48:54 lpd Exp $*/
18
/* HP DeskJet 500C driver */
19
#include "gdevprn.h"
20
#include "gdevpcl.h"
21
#include "malloc_.h"
22
 
23
/***
24
 *** Note: this driver was contributed by a user, Alfred Kayser:
25
 ***       please contact AKayser@et.tudelft.nl if you have questions.
26
 ***/
27
 
28
#ifndef SHINGLING        /* Interlaced, multi-pass printing */
29
#define SHINGLING 1      /* 0 = none, 1 = 50%, 2 = 25%, 2 is best & slowest */
30
#endif
31
 
32
#ifndef DEPLETION        /* 'Intelligent' dot-removal */ 
33
#define DEPLETION 1      /* 0 = none, 1 = 25%, 2 = 50%, 1 best for graphics? */
34
#endif                   /* Use 0 for transparencies */
35
 
36
#define X_DPI 300
37
#define Y_DPI 300
38
/* bytes per line for DeskJet Color */
39
#define LINE_SIZE ((X_DPI * 85 / 10 + 63) / 64 * 8)
40
 
41
/* The device descriptors */
42
private dev_proc_print_page(djet500c_print_page);
43
 
44
private gx_device_procs djet500c_procs =
45
  prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
46
    gdev_pcl_3bit_map_rgb_color, gdev_pcl_3bit_map_color_rgb);
47
 
48
const gx_device_printer far_data gs_djet500c_device =
49
  prn_device(djet500c_procs, "djet500c",
50
    85,                /* width_10ths, 8.5" */
51
    120,		/* height_10ths, 12" */
52
    X_DPI, Y_DPI,
53
    0.25, 0.25, 0.25, 0.25,        /* margins */
54
    3, djet500c_print_page);
55
 
56
/* Forward references */
57
private int djet500c_print_page(gx_device_printer *, FILE *);
58
 
59
static int mode2compress(byte *row, byte *end_row, byte *compressed);
60
 
61
/* The DeskJet 500C uses additive colors in separate planes. */
62
/* We only keep one bit of color, with 1 = R, 2 = G, 4 = B. */
63
/* Because the buffering routines assume 0 = white, */
64
/* we complement all the color components. */
65
 
66
/* Send the page to the printer.  For speed, compress each scan line, */
67
/* since computer-to-printer communication time is often a bottleneck. */
68
/* The DeskJet Color can compress (mode 2) */
69
 
70
private int
71
djet500c_print_page(gx_device_printer *pdev, FILE *fprn)
72
{
73
    byte *bitData=NULL;
74
    byte *plane1=NULL;
75
    byte *plane2=NULL;
76
    byte *plane3=NULL;
77
    int bitSize=0;
78
    int planeSize=0;
79
 
80
    /* select the most compressed mode available & clear tmp storage */
81
    /* put printer in known state */
82
    fputs("\033E",fprn);
83
 
84
    /* ends raster graphics to set raster graphics resolution */
85
    fputs("\033*rbC", fprn);	/*  was \033*rB  */
86
 
87
    /* set raster graphics resolution -- 300 dpi */
88
    fputs("\033*t300R", fprn);                                           
89
 
90
    /* A4, skip perf, def. paper tray */ 
91
    fputs("\033&l26a0l1H", fprn); 
92
 
93
    /* RGB Mode */
94
    fputs("\033*r3U", fprn);    
95
 
96
    /* set depletion level */
97
    fprintf(fprn, "\033*o%dD", DEPLETION);
98
 
99
    /* set shingling level */
100
    fprintf(fprn, "\033*o%dQ", SHINGLING);
101
 
102
    /* move to top left of page & set current position */
103
    fputs("\033*p0x0Y", fprn); /* cursor pos: 0,0 */
104
 
105
    fputs("\033*b2M", fprn);	/*  mode 2 compression for now  */
106
 
107
    fputs("\033*r0A", fprn);  /* start graf. left */
108
 
109
    /* Send each scan line in turn */
110
       {    int lnum;
111
	int num_blank_lines = 0;
112
	int lineSize = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
113
	if (lineSize>bitSize)
114
	{                         
115
            if (bitData) free(bitData);
116
            bitSize=lineSize;
117
            bitData=(byte*)malloc(bitSize+16);
118
	}
119
	for (lnum=0; lnum<pdev->height; lnum++)
120
	{    
121
            byte *endData;
122
 
123
            gdev_prn_copy_scan_lines(pdev, lnum, bitData, lineSize);
124
 
125
            /* Remove trailing 0s. */
126
            endData = bitData + lineSize;
127
            while ( (endData>bitData) && (endData[-1] == 0) )
128
		endData--;
129
            if (endData == bitData)
130
		num_blank_lines++;
131
            else
132
            {    int count, k, i, lineLen;
133
 
134
		/* Pad with 0s to fill out the last */
135
		/* block of 8 bytes. */
136
		memset(endData, 0, 7);
137
 
138
		lineLen=((endData-bitData)+7)/8;    /* Round to next 8multiple */           
139
		if (planeSize<lineLen)                             
140
		{
141
                    if (plane1) free(plane1);
142
                    if (plane2) free(plane2);
143
                    if (plane3) free(plane3);
144
                    planeSize=lineLen;
145
                    plane1=(byte*)malloc(planeSize+8);
146
                    plane2=(byte*)malloc(planeSize+8);
147
                    plane3=(byte*)malloc(planeSize+8);
148
		}
149
		/* Transpose the data to get pixel planes. */
150
		for (k=i=0; k<lineLen; i+=8, k++)
151
		{ 
152
                   register ushort t, c;
153
 
154
                   /* Three smaller loops are better optimizable and use less
155
                      vars, so most of them can be in registers even on pc's */
156
                   for (c=t=0;t<8;t++)
157
			c = (c<<1) | (bitData[t+i]&4);
158
                   plane3[k] = ~(byte)(c>>2);
159
                   for (c=t=0;t<8;t++)
160
			c = (c<<1) | (bitData[t+i]&2);
161
                   plane2[k] = ~(byte)(c>>1);
162
                   for (c=t=0;t<8;t++)
163
			c = (c<<1) | (bitData[t+i]&1);
164
                   plane1[k] = ~(byte)(c);
165
		}           
166
 
167
		/* Skip blank lines if any */
168
		if (num_blank_lines > 0)
169
		{    /* move down from current position */
170
                    fprintf(fprn, "\033*b%dY", num_blank_lines);
171
                    num_blank_lines = 0;
172
		}
173
 
174
		/* Transfer raster graphics */
175
		/* in the order R, G, B. */
176
		/* lineLen is at least bitSize/8, so bitData can easily be used to store
177
                   lineLen of bytes */
178
		/* P.s. mode9 compression is akward(??) to use, because the lineLenght's
179
                   are different, so we are stuck with mode 2, which is good enough */
180
 
181
		/* set the line width */
182
		fprintf(fprn, "\033*r%dS", lineLen*8);
183
 
184
		count = mode2compress(plane1, plane1 + lineLen, bitData);
185
		fprintf(fprn, "\033*b%dV", count);
186
		fwrite(bitData, sizeof(byte), count, fprn); 
187
		count = mode2compress(plane2, plane2 + lineLen, bitData);
188
		fprintf(fprn, "\033*b%dV", count);
189
		fwrite(bitData, sizeof(byte), count, fprn); 
190
		count = mode2compress(plane3, plane3 + lineLen, bitData);
191
		fprintf(fprn, "\033*b%dW", count);
192
		fwrite(bitData, sizeof(byte), count, fprn); 
193
            }
194
	}
195
    }
196
    /* end raster graphics */
197
    fputs("\033*rbC", fprn);	/*  was \033*rB  */
198
    fputs("\033*r1U", fprn);	/*  back to 1 plane  */
199
 
200
       /* put printer in known state */
201
    fputs("\033E",fprn);
202
 
203
    /* eject page */
204
    fputs("\033&l0H", fprn);        
205
 
206
    /* release allocated memory */
207
    if (bitData) free(bitData);
208
    if (plane1) free(plane1);
209
    if (plane2) free(plane2);
210
    if (plane3) free(plane3);
211
 
212
    return 0;
213
}
214
 
215
 
216
/*
217
 * Mode 2 Row compression routine for the HP DeskJet & LaserJet IIp.
218
 * Compresses data from row up to end_row, storing the result
219
 * starting at compressed.  Returns the number of bytes stored.
220
 * Runs of K<=127 literal bytes are encoded as K-1 followed by
221
 * the bytes; runs of 2<=K<=127 identical bytes are encoded as
222
 * 257-K followed by the byte.
223
 * In the worst case, the result is N+(N/127)+1 bytes long,
224
 * where N is the original byte count (end_row - row).
225
 * I can't use the general pcl version, because it assume even linelength's
226
 */
227
 
228
static int
229
mode2compress(byte *row, byte *end_row, byte *compressed)
230
{    
231
    register byte *exam; /* word being examined in the row to compress */
232
    register byte *cptr = compressed; /* output pointer into compressed bytes */
233
    int i, count, len;
234
    byte test;
235
 
236
    exam = row;
237
    while (1)
238
    {                        
239
	test = *exam++;
240
	/* Advance exam until test==*exam  or exam==end_row */
241
	while ((test != *exam) && (exam < end_row))
242
            test = *exam++;                    
243
	/* row points to start of differing bytes,
244
           exam points to start of consequtive series 
245
                    or to end of row */
246
	if (exam<end_row) exam--;
247
	len=exam-row;   
248
	while (len>0)
249
	{
250
            count=len;
251
            if (count>127) count=127;
252
            *cptr++=count-1;  
253
            for (i=0;i<count;i++) *cptr++ = *row++;
254
            len-=count;
255
	}     
256
	if (exam>=end_row) break;     /* done */             
257
	exam++;     /* skip first same byte */
258
	while ((test == *exam) && (exam < end_row))  /* skip all same bytes */
259
            exam++;
260
	/* exam points now first different word or to end of data */
261
	len = exam-row;
262
	while (len>0)
263
	{     
264
            count=len;
265
            if (count>127) count=127;
266
            *cptr++=(257-count);
267
            *cptr++=test;             
268
            len-=count;
269
	}                
270
	if (exam>=end_row) break;            /* end of data */
271
	row = exam;    /* row points to first dissimular byte */
272
    }                                          
273
    return (cptr-compressed);
274
}