xref: /plan9/sys/src/cmd/gs/src/gdevccr.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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