/* Copyright (C) 1996, 1997 artofcode LLC. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA, 02111-1307. */ /*$Id: gdevccr.c,v 1.2.6.1.2.1 2003/01/17 00:49:00 giles Exp $*/ /* CalComp Raster Format driver */ #include "gdevprn.h" /* * Please contact the author, Ernst Muellner (ernst.muellner@oenzl.siemens.de), * if you have any questions about this driver. */ #define CCFILESTART(p) putc(0x02, p) #define CCFILEEND(p) putc(0x04, p) #define CCNEWPASS(p) putc(0x0c, p) #define CCEMPTYLINE(p) putc(0x0a, p) #define CCLINESTART(len,p) do{ putc(0x1b,p);putc(0x4b,p);putc(len>>8,p); \ putc(len&0xff,p);} while(0) #define CPASS (0) #define MPASS (1) #define YPASS (2) #define NPASS (3) typedef struct cmyrow_s { int current; int _cmylen[NPASS]; int is_used; char cname[4]; char mname[4]; char yname[4]; unsigned char *_cmybuf[NPASS]; } cmyrow; #define clen _cmylen[CPASS] #define mlen _cmylen[MPASS] #define ylen _cmylen[YPASS] #define cmylen _cmylen #define cbuf _cmybuf[CPASS] #define mbuf _cmybuf[MPASS] #define ybuf _cmybuf[YPASS] #define cmybuf _cmybuf private int alloc_rb( cmyrow **rb, int rows); private int alloc_line( cmyrow *row, int cols); private void add_cmy8(cmyrow *rb, char c, char m, char y); private void write_cpass(cmyrow *buf, int rows, int pass, FILE * pstream); private void free_rb_line( cmyrow *rbuf, int rows, int cols); struct gx_device_ccr_s { gx_device_common; gx_prn_device_common; /* optional parameters */ }; typedef struct gx_device_ccr_s gx_device_ccr; #define bdev ((gx_device_ccr *)pdev) /* ------ The device descriptors ------ */ /* * Default X and Y resolution. */ #define X_DPI 300 #define Y_DPI 300 #define DEFAULT_WIDTH_10THS_A3 117 #define DEFAULT_HEIGHT_10THS_A3 165 /* Macro for generating ccr device descriptors. */ #define ccr_prn_device(procs, dev_name, margin, num_comp, depth, max_gray, max_rgb, print_page)\ { prn_device_body(gx_device_ccr, procs, dev_name,\ DEFAULT_WIDTH_10THS_A3, DEFAULT_HEIGHT_10THS_A3, X_DPI, Y_DPI,\ margin, margin, margin, margin,\ num_comp, depth, max_gray, max_rgb, max_gray + 1, max_rgb + 1,\ print_page)\ } /* For CCR, we need our own color mapping procedures. */ private dev_proc_map_rgb_color(ccr_map_rgb_color); private dev_proc_map_color_rgb(ccr_map_color_rgb); /* And of course we need our own print-page routine. */ private dev_proc_print_page(ccr_print_page); /* The device procedures */ private gx_device_procs ccr_procs = prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close, ccr_map_rgb_color, ccr_map_color_rgb); /* The device descriptors themselves */ gx_device_ccr far_data gs_ccr_device = ccr_prn_device(ccr_procs, "ccr", 0.2, 3, 8, 1, 1, ccr_print_page); /* ------ Color mapping routines ------ */ /* map an rgb color to a ccr cmy bitmap */ private gx_color_index ccr_map_rgb_color(gx_device *pdev, ushort r, ushort g, ushort b) { register int shift = gx_color_value_bits - 1; r>>=shift; g>>=shift; b>>=shift; r=1-r; g=1-g; b=1-b; /* rgb -> cmy */ return r<<2 | g<<1 | b; } /* map an ccr cmy bitmap to a rgb color */ private int ccr_map_color_rgb(gx_device *pdev, gx_color_index color, ushort rgb[3]) { rgb[2]=(1-(color >>2))*gx_max_color_value; /* r */ rgb[1]=(1-( (color & 0x2) >> 1))*gx_max_color_value; /* g */ rgb[0]=(1-(color & 0x1))*gx_max_color_value; /* b */ return 0; } /* ------ print page routine ------ */ private int ccr_print_page(gx_device_printer *pdev, FILE *pstream) { cmyrow *linebuf; int line_size = gdev_prn_raster((gx_device *)pdev); int pixnum = pdev->width; int lnum = pdev->height; int l, p, b; int cmy, c, m, y; byte *in; byte *data; if((in = (byte *)gs_malloc(line_size, 1, "gsline")) == NULL) return_error(gs_error_VMerror); if(alloc_rb( &linebuf, lnum)) { gs_free(in, line_size, 1, "gsline"); return_error(gs_error_VMerror); } for ( l = 0; l < lnum; l++ ) { gdev_prn_get_bits(pdev, l, in, &data); if(alloc_line(&linebuf[l], pixnum)) { gs_free(in, line_size, 1, "gsline"); free_rb_line( linebuf, lnum, pixnum ); return_error(gs_error_VMerror); } for ( p=0; p< pixnum; p+=8) { c=m=y=0; for(b=0; b<8; b++) { c <<= 1; m <<= 1; y <<= 1; if(p+b < pixnum) cmy = *data; else cmy = 0; c |= cmy>>2; m |= (cmy>>1) & 0x1; y |= cmy & 0x1; data++; } add_cmy8(&linebuf[l], c, m, y); } } CCFILESTART(pstream); write_cpass(linebuf, lnum, YPASS, pstream); CCNEWPASS(pstream); write_cpass(linebuf, lnum, MPASS, pstream); CCNEWPASS(pstream); write_cpass(linebuf, lnum, CPASS, pstream); CCFILEEND(pstream); /* clean up */ gs_free(in, line_size, 1, "gsline"); free_rb_line( linebuf, lnum, pixnum ); return 0; } /* ------ Internal routines ------ */ private int alloc_rb( cmyrow **rb, int rows) { *rb = (cmyrow*) gs_malloc(rows, sizeof(cmyrow), "rb"); if( *rb == 0) return_error(gs_error_VMerror); else { int r; for(r=0; rcbuf = (unsigned char *) gs_malloc(cols,1, row->cname)) && (row->mbuf = (unsigned char *) gs_malloc(cols,1, row->mname)) && (row->ybuf = (unsigned char *) gs_malloc(cols,1, row->yname))); if(suc == 0) { gs_free(row->cbuf, cols,1, row->cname); gs_free(row->mbuf, cols,1, row->mname); gs_free(row->ybuf, cols,1, row->yname); return_error(gs_error_VMerror); } row->is_used = 1; row->current = row->clen = row->mlen = row->ylen = 0; return 0; } private void add_cmy8(cmyrow *rb, char c, char m, char y) { int cur=rb->current; rb->cbuf[cur]=c; if(c) rb->clen=cur+1; rb->mbuf[cur]=m; if(m) rb->mlen=cur+1; rb->ybuf[cur]=y; if(y) rb->ylen=cur+1; rb->current++; return; } private void write_cpass(cmyrow *buf, int rows, int pass, FILE * pstream) { int row, len; for(row=0; row