1 /* Copyright (C) 1996, 1997 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: gdevccr.c,v 1.6 2005/01/19 00:24:07 dan Exp $*/
18 /* CalComp Raster Format driver */
19 #include "gdevprn.h"
20
21 /*
22 * Please contact the author, Ernst Muellner (ernst.muellner@oenzl.siemens.de),
23 * if you have any questions about this driver.
24 */
25
26 #define CCFILESTART(p) putc(0x02, p)
27 #define CCFILEEND(p) putc(0x04, p)
28 #define CCNEWPASS(p) putc(0x0c, p)
29 #define CCEMPTYLINE(p) putc(0x0a, p)
30 #define CCLINESTART(len,p) do{ putc(0x1b,p);putc(0x4b,p);putc(len>>8,p); \
31 putc(len&0xff,p);} while(0)
32
33 #define CPASS (0)
34 #define MPASS (1)
35 #define YPASS (2)
36 #define NPASS (3)
37
38
39 typedef struct cmyrow_s
40 {
41 int current;
42 int _cmylen[NPASS];
43 int is_used;
44 char cname[4];
45 char mname[4];
46 char yname[4];
47 unsigned char *_cmybuf[NPASS];
48 } cmyrow;
49
50 #define clen _cmylen[CPASS]
51 #define mlen _cmylen[MPASS]
52 #define ylen _cmylen[YPASS]
53 #define cmylen _cmylen
54
55 #define cbuf _cmybuf[CPASS]
56 #define mbuf _cmybuf[MPASS]
57 #define ybuf _cmybuf[YPASS]
58 #define cmybuf _cmybuf
59
60 private int alloc_rb( gs_memory_t *mem, cmyrow **rb, int rows);
61 private int alloc_line( gs_memory_t *mem, cmyrow *row, int cols);
62 private void add_cmy8(cmyrow *rb, char c, char m, char y);
63 private void write_cpass(cmyrow *buf, int rows, int pass, FILE * pstream);
64 private void free_rb_line( gs_memory_t *mem, cmyrow *rbuf, int rows, int cols);
65
66 struct gx_device_ccr_s {
67 gx_device_common;
68 gx_prn_device_common;
69 /* optional parameters */
70 };
71 typedef struct gx_device_ccr_s gx_device_ccr;
72
73 #define bdev ((gx_device_ccr *)pdev)
74
75 /* ------ The device descriptors ------ */
76
77 /*
78 * Default X and Y resolution.
79 */
80 #define X_DPI 300
81 #define Y_DPI 300
82 #define DEFAULT_WIDTH_10THS_A3 117
83 #define DEFAULT_HEIGHT_10THS_A3 165
84
85 /* Macro for generating ccr device descriptors. */
86 #define ccr_prn_device(procs, dev_name, margin, num_comp, depth, max_gray, max_rgb, print_page)\
87 { prn_device_body(gx_device_ccr, procs, dev_name,\
88 DEFAULT_WIDTH_10THS_A3, DEFAULT_HEIGHT_10THS_A3, X_DPI, Y_DPI,\
89 margin, margin, margin, margin,\
90 num_comp, depth, max_gray, max_rgb, max_gray + 1, max_rgb + 1,\
91 print_page)\
92 }
93
94 /* For CCR, we need our own color mapping procedures. */
95 private dev_proc_map_rgb_color(ccr_map_rgb_color);
96 private dev_proc_map_color_rgb(ccr_map_color_rgb);
97
98
99 /* And of course we need our own print-page routine. */
100 private dev_proc_print_page(ccr_print_page);
101
102 /* The device procedures */
103 private gx_device_procs ccr_procs =
104 prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
105 ccr_map_rgb_color, ccr_map_color_rgb);
106
107 /* The device descriptors themselves */
108 gx_device_ccr far_data gs_ccr_device =
109 ccr_prn_device(ccr_procs, "ccr", 0.2, 3, 8, 1, 1,
110 ccr_print_page);
111
112 /* ------ Color mapping routines ------ */
113 /* map an rgb color to a ccr cmy bitmap */
114 private gx_color_index
ccr_map_rgb_color(gx_device * pdev,const ushort cv[])115 ccr_map_rgb_color(gx_device *pdev, const ushort cv[])
116 {
117 ushort r, g, b;
118 register int shift = gx_color_value_bits - 1;
119
120 r = cv[0]; g = cv[1]; b = cv[2];
121 r>>=shift;
122 g>>=shift;
123 b>>=shift;
124
125 r=1-r; g=1-g; b=1-b; /* rgb -> cmy */
126 return r<<2 | g<<1 | b;
127 }
128
129 /* map an ccr cmy bitmap to a rgb color */
130 private int
ccr_map_color_rgb(gx_device * pdev,gx_color_index color,ushort rgb[3])131 ccr_map_color_rgb(gx_device *pdev, gx_color_index color, ushort rgb[3])
132 {
133 rgb[2]=(1-(color >>2))*gx_max_color_value; /* r */
134 rgb[1]=(1-( (color & 0x2) >> 1))*gx_max_color_value; /* g */
135 rgb[0]=(1-(color & 0x1))*gx_max_color_value; /* b */
136 return 0;
137 }
138 /* ------ print page routine ------ */
139
140
141 private int
ccr_print_page(gx_device_printer * pdev,FILE * pstream)142 ccr_print_page(gx_device_printer *pdev, FILE *pstream)
143 {
144 cmyrow *linebuf;
145 int line_size = gdev_prn_raster((gx_device *)pdev);
146 int pixnum = pdev->width;
147 int lnum = pdev->height;
148 int l, p, b;
149 int cmy, c, m, y;
150 byte *in;
151 byte *data;
152
153 if((in = (byte *)gs_malloc(pdev->memory, line_size, 1, "gsline")) == NULL)
154 return_error(gs_error_VMerror);
155
156 if(alloc_rb( pdev->memory, &linebuf, lnum))
157 {
158 gs_free(pdev->memory, in, line_size, 1, "gsline");
159 return_error(gs_error_VMerror);
160 }
161
162 for ( l = 0; l < lnum; l++ )
163 { gdev_prn_get_bits(pdev, l, in, &data);
164 if(alloc_line(pdev->memory, &linebuf[l], pixnum))
165 {
166 gs_free(pdev->memory, in, line_size, 1, "gsline");
167 free_rb_line( pdev->memory, linebuf, lnum, pixnum );
168 return_error(gs_error_VMerror);
169 }
170 for ( p=0; p< pixnum; p+=8)
171 {
172 c=m=y=0;
173 for(b=0; b<8; b++)
174 {
175 c <<= 1; m <<= 1; y <<= 1;
176 if(p+b < pixnum)
177 cmy = *data;
178 else
179 cmy = 0;
180
181 c |= cmy>>2;
182 m |= (cmy>>1) & 0x1;
183 y |= cmy & 0x1;
184 data++;
185 }
186 add_cmy8(&linebuf[l], c, m, y);
187 }
188 }
189 CCFILESTART(pstream);
190 write_cpass(linebuf, lnum, YPASS, pstream);
191 CCNEWPASS(pstream);
192 write_cpass(linebuf, lnum, MPASS, pstream);
193 CCNEWPASS(pstream);
194 write_cpass(linebuf, lnum, CPASS, pstream);
195 CCFILEEND(pstream);
196
197 /* clean up */
198 gs_free(pdev->memory, in, line_size, 1, "gsline");
199 free_rb_line( pdev->memory, linebuf, lnum, pixnum );
200 return 0;
201 }
202
203
204 /* ------ Internal routines ------ */
205
206
alloc_rb(gs_memory_t * mem,cmyrow ** rb,int rows)207 private int alloc_rb( gs_memory_t *mem, cmyrow **rb, int rows)
208 {
209 *rb = (cmyrow*) gs_malloc(mem, rows, sizeof(cmyrow), "rb");
210 if( *rb == 0)
211 return_error(gs_error_VMerror);
212 else
213 {
214 int r;
215 for(r=0; r<rows; r++)
216 {
217 sprintf((*rb)[r].cname, "C%02x", r);
218 sprintf((*rb)[r].mname, "M%02x", r);
219 sprintf((*rb)[r].yname, "Y%02x", r);
220 (*rb)[r].is_used=0;
221 }
222 return 0;
223 }
224 }
225
alloc_line(gs_memory_t * mem,cmyrow * row,int cols)226 private int alloc_line( gs_memory_t *mem, cmyrow *row, int cols)
227 {
228 int suc;
229 suc=((row->cbuf = (unsigned char *) gs_malloc(mem, cols,1, row->cname)) &&
230 (row->mbuf = (unsigned char *) gs_malloc(mem, cols,1, row->mname)) &&
231 (row->ybuf = (unsigned char *) gs_malloc(mem, cols,1, row->yname)));
232 if(suc == 0)
233 {
234 gs_free(mem, row->cbuf, cols,1, row->cname);
235 gs_free(mem, row->mbuf, cols,1, row->mname);
236 gs_free(mem, row->ybuf, cols,1, row->yname);
237
238 return_error(gs_error_VMerror);
239 }
240 row->is_used = 1;
241 row->current = row->clen = row->mlen = row->ylen = 0;
242 return 0;
243 }
244
add_cmy8(cmyrow * rb,char c,char m,char y)245 private void add_cmy8(cmyrow *rb, char c, char m, char y)
246 {
247 int cur=rb->current;
248 rb->cbuf[cur]=c;
249 if(c)
250 rb->clen=cur+1;
251 rb->mbuf[cur]=m;
252 if(m)
253 rb->mlen=cur+1;
254 rb->ybuf[cur]=y;
255 if(y)
256 rb->ylen=cur+1;
257 rb->current++;
258 return;
259 }
260
write_cpass(cmyrow * buf,int rows,int pass,FILE * pstream)261 private void write_cpass(cmyrow *buf, int rows, int pass, FILE * pstream)
262 {
263 int row, len;
264 for(row=0; row<rows; row++)
265 {
266 len=buf[row].cmylen[pass];
267 if(len == 0)
268 CCEMPTYLINE(pstream);
269 else
270 {
271 CCLINESTART(len,pstream);
272 fwrite( buf[row].cmybuf[pass], len, 1, pstream);
273 }
274 }
275 return;
276 }
277
free_rb_line(gs_memory_t * mem,cmyrow * rbuf,int rows,int cols)278 private void free_rb_line( gs_memory_t *mem, cmyrow *rbuf, int rows, int cols)
279 {
280 int i;
281 for(i=0; i<rows; i++)
282 {
283 if(rbuf[i].is_used)
284 {
285 gs_free(mem, rbuf[i].cbuf, cols, 1, rbuf[i].cname);
286 gs_free(mem, rbuf[i].mbuf, cols, 1, rbuf[i].mname);
287 gs_free(mem, rbuf[i].ybuf, cols, 1, rbuf[i].yname);
288 rbuf[i].is_used = 0;
289 }
290 else
291 break;
292 }
293 gs_free( mem, rbuf, rows, sizeof(cmyrow), "rb");
294 return;
295 }
296