2 |
- |
1 |
/* Copyright (C) 1992, 1996 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: gdevtknk.c,v 1.6 2002/08/22 07:12:28 henrys Exp $*/
|
|
|
18 |
/*
|
|
|
19 |
This driver is written for Tektronix ink-jet 4696 and 4695 plotters.
|
|
|
20 |
|
|
|
21 |
It may easily be adopted to the 4393 and 4394 models as well, simply by
|
|
|
22 |
adding new device descriptors with other geometrical characteristics.
|
|
|
23 |
*/
|
|
|
24 |
#include "gdevprn.h"
|
|
|
25 |
#include "malloc_.h"
|
|
|
26 |
|
|
|
27 |
/* Thanks to Karsten Spang (spang@nbivax.nbi.dk) for contributing */
|
|
|
28 |
/* this code to Aladdin Enterprises. */
|
|
|
29 |
|
|
|
30 |
|
|
|
31 |
/* The device descriptor */
|
|
|
32 |
/* We need our own color mapping procedures. */
|
|
|
33 |
private dev_proc_map_rgb_color(tekink_map_rgb_color);
|
|
|
34 |
private dev_proc_map_color_rgb(tekink_map_color_rgb);
|
|
|
35 |
private dev_proc_print_page(tekink_print_page);
|
|
|
36 |
private gx_device_procs tekink_procs =
|
|
|
37 |
prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
|
|
|
38 |
tekink_map_rgb_color, tekink_map_color_rgb);
|
|
|
39 |
|
|
|
40 |
|
|
|
41 |
/*
|
|
|
42 |
Device descriptor for the Tek 4696.
|
|
|
43 |
The 4696 plotter uses roll media, thus the y size is arbitrary. The
|
|
|
44 |
value below is chosen to make the image area A*-format like, i.e. the
|
|
|
45 |
aspect ratio is close to sqrt(2).
|
|
|
46 |
*/
|
|
|
47 |
const gx_device_printer far_data gs_tek4696_device =
|
|
|
48 |
prn_device(tekink_procs,"tek4696",
|
|
|
49 |
85,120, /* Page size in 10th of inches */
|
|
|
50 |
120,120, /* Resolution in DPI */
|
|
|
51 |
0.0,0.0,0.0,0.0, /* Margins */
|
|
|
52 |
4, /* Bits per pixel */
|
|
|
53 |
tekink_print_page);
|
|
|
54 |
|
|
|
55 |
/* Color mapping.
|
|
|
56 |
The tek inkjets use subtractive colors B=0 M=1 Y=2 C=3. These are
|
|
|
57 |
represented as 4 bits B=1 M=2 Y=4 C=8 in a byte. This gives:
|
|
|
58 |
White = 0
|
|
|
59 |
Black = 1
|
|
|
60 |
Magenta = 2
|
|
|
61 |
Yellow = 4
|
|
|
62 |
Red = 6
|
|
|
63 |
Cyan = 8
|
|
|
64 |
Blue = 10
|
|
|
65 |
Green = 12
|
|
|
66 |
The remaining values are unused. (They give ugly results if sent to the
|
|
|
67 |
plotter.) Of course this could have been compressed into 3 bits, but
|
|
|
68 |
as the palette color memory device uses 8 bits anyway, this is easier,
|
|
|
69 |
and perhaps faster.
|
|
|
70 |
*/
|
|
|
71 |
|
|
|
72 |
static gx_color_index rgb_to_index[8]={1,6,12,4,10,2,8,0};
|
|
|
73 |
static ushort index_to_rgb[16][3]={
|
|
|
74 |
{65535,65535,65535}, /* White */
|
|
|
75 |
{0,0,0}, /* Black */
|
|
|
76 |
{65535,0,65535}, /* Magenta */
|
|
|
77 |
{2,2,2}, /* Unused */
|
|
|
78 |
{65535,65535,0}, /* Yellow */
|
|
|
79 |
{2,2,2}, /* Unused */
|
|
|
80 |
{65535,0,0}, /* Red */
|
|
|
81 |
{2,2,2}, /* Unused */
|
|
|
82 |
{0,65535,65535}, /* Cyan */
|
|
|
83 |
{2,2,2}, /* Unused */
|
|
|
84 |
{0,0,65535}, /* Blue */
|
|
|
85 |
{2,2,2}, /* Unused */
|
|
|
86 |
{0,65535,0}, /* Green */
|
|
|
87 |
{2,2,2}, /* Unused */
|
|
|
88 |
{2,2,2}, /* Unused */
|
|
|
89 |
{2,2,2} /* Unused */
|
|
|
90 |
};
|
|
|
91 |
|
|
|
92 |
/* Map an RGB color to a printer color. */
|
|
|
93 |
private gx_color_index
|
|
|
94 |
tekink_map_rgb_color(gx_device *dev, const gx_color_value cv[])
|
|
|
95 |
{
|
|
|
96 |
gx_color_value r = cv[0];
|
|
|
97 |
gx_color_value g = cv[1];
|
|
|
98 |
gx_color_value b = cv[2];
|
|
|
99 |
|
|
|
100 |
return(rgb_to_index[(((b>32767) << 2) + ((g>32767) << 1) +
|
|
|
101 |
(r>32767)) & 7]);
|
|
|
102 |
}
|
|
|
103 |
|
|
|
104 |
/* Map the printer color back to RGB. */
|
|
|
105 |
private int
|
|
|
106 |
tekink_map_color_rgb(gx_device *dev, gx_color_index color, ushort prgb[3])
|
|
|
107 |
{
|
|
|
108 |
register ushort c = (ushort)color;
|
|
|
109 |
register int i;
|
|
|
110 |
if (c>15) return -1;
|
|
|
111 |
if (index_to_rgb[c][0]==2) return -1;
|
|
|
112 |
for (i=0;i<3;i++){
|
|
|
113 |
prgb[i]=index_to_rgb[c][i];
|
|
|
114 |
}
|
|
|
115 |
return 0;
|
|
|
116 |
}
|
|
|
117 |
|
|
|
118 |
/* Send the page to the printer. */
|
|
|
119 |
private int
|
|
|
120 |
tekink_print_page(gx_device_printer *pdev,FILE *prn_stream)
|
|
|
121 |
{
|
|
|
122 |
int line_size,color_line_size,scan_line,num_bytes,scan_lines,color_plane;
|
|
|
123 |
int roll_paper,out_line,micro_line,pending_micro_lines,line_blank,
|
|
|
124 |
blank_lines;
|
|
|
125 |
byte *outdata,*indata1,*bdata1,*mdata1,*ydata1,*cdata1;
|
|
|
126 |
register byte *indata,*bdatap,*mdatap,*ydatap,*cdatap;
|
|
|
127 |
register byte bdata,mdata,ydata,cdata;
|
|
|
128 |
register byte mask,inbyte;
|
|
|
129 |
register byte *indataend,*outdataend;
|
|
|
130 |
|
|
|
131 |
/* Allocate a temporary buffer for color separation.
|
|
|
132 |
The buffer is partitioned into an input buffer and four
|
|
|
133 |
output buffers for the color planes. The output buffers
|
|
|
134 |
are allocated with an extra sentinel byte. */
|
|
|
135 |
|
|
|
136 |
line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
|
|
|
137 |
color_line_size=(pdev->width+7)/8;
|
|
|
138 |
indata1=(byte *)malloc(line_size+4*(color_line_size+1));
|
|
|
139 |
if (indata1==NULL) return -1;
|
|
|
140 |
/* pointers to the partions */
|
|
|
141 |
indataend=indata1+line_size;
|
|
|
142 |
bdata1=indataend;
|
|
|
143 |
mdata1=bdata1+(color_line_size+1);
|
|
|
144 |
ydata1=mdata1+(color_line_size+1);
|
|
|
145 |
cdata1=ydata1+(color_line_size+1);
|
|
|
146 |
|
|
|
147 |
/* Does this device use roll paper? */
|
|
|
148 |
roll_paper=!strcmp(pdev->dname,"tek4696");
|
|
|
149 |
|
|
|
150 |
out_line=0;
|
|
|
151 |
blank_lines=0;
|
|
|
152 |
scan_lines=pdev->height;
|
|
|
153 |
for (scan_line=0;scan_line<scan_lines;scan_line++){
|
|
|
154 |
/* get data */
|
|
|
155 |
gdev_prn_copy_scan_lines(pdev,scan_line,indata1,line_size);
|
|
|
156 |
/* Separate data into color planes */
|
|
|
157 |
bdatap = bdata1+1;
|
|
|
158 |
mdatap = mdata1+1;
|
|
|
159 |
ydatap = ydata1+1;
|
|
|
160 |
cdatap = cdata1+1;
|
|
|
161 |
bdata=0;
|
|
|
162 |
mdata=0;
|
|
|
163 |
cdata=0;
|
|
|
164 |
ydata=0;
|
|
|
165 |
mask=0x80;
|
|
|
166 |
memset(indataend,0,4*(color_line_size+1));
|
|
|
167 |
for (indata=indata1;indata<indataend;indata++){
|
|
|
168 |
inbyte = *indata;
|
|
|
169 |
if (inbyte&0x01) bdata|=mask;
|
|
|
170 |
if (inbyte&0x02) mdata|=mask;
|
|
|
171 |
if (inbyte&0x04) ydata|=mask;
|
|
|
172 |
if (inbyte&0x08) cdata|=mask;
|
|
|
173 |
mask>>=1;
|
|
|
174 |
if (!mask){
|
|
|
175 |
*(bdatap++) = bdata;
|
|
|
176 |
*(mdatap++) = mdata;
|
|
|
177 |
*(cdatap++) = cdata;
|
|
|
178 |
*(ydatap++) = ydata;
|
|
|
179 |
bdata=0;
|
|
|
180 |
mdata=0;
|
|
|
181 |
cdata=0;
|
|
|
182 |
ydata=0;
|
|
|
183 |
mask=0x80;
|
|
|
184 |
}
|
|
|
185 |
}
|
|
|
186 |
if (mask!=0x80){
|
|
|
187 |
*bdatap = bdata;
|
|
|
188 |
*mdatap = mdata;
|
|
|
189 |
*cdatap = cdata;
|
|
|
190 |
*ydatap = ydata;
|
|
|
191 |
}
|
|
|
192 |
line_blank=1;
|
|
|
193 |
/* Output each of the four color planes */
|
|
|
194 |
for (color_plane=0;color_plane<4;color_plane++){
|
|
|
195 |
outdata=indataend+(color_plane*(color_line_size+1));
|
|
|
196 |
outdataend=outdata+color_line_size;
|
|
|
197 |
|
|
|
198 |
/* Remove trailing spaces and output the color line if it is
|
|
|
199 |
not blank */
|
|
|
200 |
*outdata=0xff;
|
|
|
201 |
while (!(*outdataend)) outdataend--;
|
|
|
202 |
if (num_bytes=(outdataend-outdata)){
|
|
|
203 |
line_blank=0;
|
|
|
204 |
/* On encountering the first non-blank data, output pending
|
|
|
205 |
blank lines */
|
|
|
206 |
if (blank_lines){
|
|
|
207 |
pending_micro_lines=((out_line+blank_lines+1)/4)-
|
|
|
208 |
(out_line/4);
|
|
|
209 |
for (micro_line=0;micro_line<pending_micro_lines;
|
|
|
210 |
micro_line++){
|
|
|
211 |
fputs("\033A",prn_stream);
|
|
|
212 |
}
|
|
|
213 |
out_line+=blank_lines;
|
|
|
214 |
blank_lines=0;
|
|
|
215 |
}
|
|
|
216 |
fprintf(prn_stream,"\033I%c%03d",'0'+(out_line%4)+
|
|
|
217 |
4*color_plane,num_bytes);
|
|
|
218 |
fwrite(outdata+1,1,num_bytes,prn_stream);
|
|
|
219 |
}
|
|
|
220 |
} /* loop over color planes */
|
|
|
221 |
|
|
|
222 |
/* If this line is blank, and if it is a roll paper model,
|
|
|
223 |
count the line. Otherwise output the line */
|
|
|
224 |
if (line_blank&&roll_paper){
|
|
|
225 |
/* Only increment the blank line count, if non blank lines
|
|
|
226 |
have been encountered previously, i.e. skip leading blank
|
|
|
227 |
lines. */
|
|
|
228 |
if (out_line) blank_lines++;
|
|
|
229 |
}
|
|
|
230 |
else{
|
|
|
231 |
if (out_line%4==3){
|
|
|
232 |
/* Write micro line feed code */
|
|
|
233 |
fputs("\033A",prn_stream);
|
|
|
234 |
}
|
|
|
235 |
out_line++;
|
|
|
236 |
}
|
|
|
237 |
} /* loop over scan lines */
|
|
|
238 |
|
|
|
239 |
/* if the number of scan lines written is not a multiple of four,
|
|
|
240 |
write the final micro line feed code */
|
|
|
241 |
if (out_line%4){
|
|
|
242 |
fputs("\033A",prn_stream);
|
|
|
243 |
}
|
|
|
244 |
/* Separate this plot from the next */
|
|
|
245 |
if (roll_paper){
|
|
|
246 |
fputs("\n\n\n\n\n",prn_stream);
|
|
|
247 |
}
|
|
|
248 |
else{
|
|
|
249 |
fputs("\f",prn_stream);
|
|
|
250 |
}
|
|
|
251 |
|
|
|
252 |
/* Deallocate temp buffer */
|
|
|
253 |
free(indata1);
|
|
|
254 |
return 0;
|
|
|
255 |
}
|