1 /* Copyright (C) 1990, 1992, 1993 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: gdevsj48.c,v 1.5 2004/08/10 13:02:36 stefan Exp $*/
18 /*
19 * StarJet SJ48 printer driver.
20 *
21 * --- derived from gdevbj10.c 1993-10-07
22 * by Mats kerblom (f86ma@dd.chalmers.se).
23 */
24
25 #include "gdevprn.h"
26
27
28 /*
29 * The only available resolutions (in the program) are (180,360)x(180,360).
30 *
31 * Used control codes:
32 * <Esc>@ Printer reset
33 * <Esc>J<n> Make a n/180 inch linefeed
34 * <Esc>\<a><b> Move the print position (a+256b)/180 inch to the right
35 * <Esc>*<m><a><b>... Print graphics; m=39: 180*180 dpi
36 * m=40: 360*180 dpi
37 * m=71: 180*360 dpi
38 * m=72: 360*360 dpi
39 * a+256b columns is printed.
40 */
41
42 /* The device descriptor */
43 private dev_proc_print_page(sj48_print_page);
44 gx_device_printer far_data gs_sj48_device =
45 prn_device(prn_std_procs, "sj48",
46 80, /* width_10ths, 8" */
47 105, /* height_10ths, 10.5" */
48 360, /* x_dpi */
49 360, /* y_dpi */
50 0,0,0,0, /* margins */
51 1, sj48_print_page);
52
53
54 /* This comes from the bj10/bj200 source. I don't know how it applies
55 * for a StarJet. --- Mats kerblom.
56 *
57 *
58 * The following is taken from the BJ200 Programmer's manual. The top
59 * margin is 3mm (0.12"), and the bottom margin is 6.4mm (0.25"). The
60 * left and right margin depend on the type of paper -- US letter or
61 * A4 -- but ultimately rest on a print width of 203.2mm (8"). For letter
62 * paper, the left margin (and hence the right) is 6.4mm (0.25"), while
63 * for A4 paper, both are 3.4mm (0.13").
64 *
65 * The bottom margin requires a bit of care. The image is printed
66 * as strips, each about 3.4mm wide. We can only attain the bottom
67 * margin if the final strip coincides with it. Note that each strip
68 * is generated using only 48 of the available 64 jets, and the absence
69 * of those bottom 16 jets makes our bottom margin, in effect, about
70 * 1.1mm (0.04") larger.
71 *
72 * The bj200 behaves, in effect, as though the origin were at the first
73 * printable position, rather than the top left corner of the page, so
74 * we add a translation to the initial matrix to compensate for this.
75 *
76 * Except for the details of getting the margins correct, the bj200 is
77 * no different from the bj10e, and uses the same routine to print each
78 * page.
79 *
80 */
81
82
83 /* Send the page to the printer. */
84 private int
sj48_print_page(gx_device_printer * pdev,FILE * prn_stream)85 sj48_print_page(gx_device_printer *pdev, FILE *prn_stream)
86 { int line_size = gx_device_raster((gx_device *)pdev, 0);
87 int xres = pdev->x_pixels_per_inch;
88 int yres = pdev->y_pixels_per_inch;
89 int mode = (yres == 180 ?
90 (xres == 180 ? 39 : 40) :
91 (xres == 180 ? 71 : 72));
92 int bytes_per_column = (yres == 180) ? 3 : 6;
93 int bits_per_column = bytes_per_column * 8;
94 int skip_unit = bytes_per_column * (xres == 180 ? 1 : 2); /* Skips in step of 1/180" */
95 byte *in = (byte *)gs_malloc(pdev->memory, 8, line_size, "sj48_print_page(in)");
96 byte *out = (byte *)gs_malloc(pdev->memory, bits_per_column, line_size, "sj48_print_page(out)");
97 int lnum = 0;
98 int skip = 0;
99 int skips;
100 int code = 0;
101 int last_row = dev_print_scan_lines(pdev);
102 int limit = last_row - bits_per_column;
103
104 if ( in == 0 || out == 0 )
105 { code = gs_error_VMerror;
106 gs_note_error(code);
107 goto fin;
108 }
109
110 /* Abort if the requested resolution is unsupported. */
111 if ((xres !=180 && xres != 360) || (yres !=180 && yres != 360))
112 { code = gs_error_rangecheck;
113 gs_note_error(code);
114 goto fin;
115 }
116
117 /* Initialize the printer. */
118 fwrite("\033@\000\000", 1, 4, prn_stream); /* <Printer reset>, <0>, <0>. */
119
120 /* Transfer pixels to printer. The last row we can print is defined
121 by "last_row". Only the bottom of the print head can print at the
122 bottom margin, and so we align the final printing pass. The print
123 head is kept from moving below "limit", which is exactly one pass
124 above the bottom margin. Once it reaches this limit, we make our
125 final printing pass of a full "bits_per_column" rows. */
126 while ( lnum < last_row )
127 {
128 byte *in_data;
129 byte *in_end = in + line_size;
130 byte *out_beg = out;
131 byte *out_end = out + bytes_per_column * pdev->width;
132 byte *outl = out;
133 int count, bnum;
134
135 /* Copy 1 scan line and test for all zero. */
136 code = gdev_prn_get_bits(pdev, lnum, in, &in_data);
137 if ( code < 0 ) goto xit;
138 /* The mem... or str... functions should be faster than */
139 /* the following code, but all systems seem to implement */
140 /* them so badly that this code is faster. */
141 { register const long *zip = (const long *)in_data;
142 register int zcnt = line_size;
143 register const byte *zipb;
144 for ( ; zcnt >= 4 * sizeof(long); zip += 4, zcnt -= 4 * sizeof(long) )
145 { if ( zip[0] | zip[1] | zip[2] | zip[3] )
146 goto notz;
147 }
148 zipb = (const byte *)zip;
149 while ( --zcnt >= 0 )
150 {
151 if ( *zipb++ )
152 goto notz;
153 }
154 /* Line is all zero, skip */
155 lnum++;
156 skip++;
157 continue;
158 notz: ;
159 }
160
161 /* Vertical tab to the appropriate position. Note here that
162 we make sure we don't move below limit. */
163 if ( lnum > limit )
164 { skip -= (limit - lnum);
165 lnum = limit;
166 }
167
168 /* The SJ48 can only skip in steps of 1/180" */
169 if (yres == 180) {
170 skips = skip;
171 } else {
172 if (skip & 1) {
173 skip--; /* Makes skip even. */
174 lnum--;
175 }
176 skips = skip/2;
177 }
178
179 while ( skips > 255 )
180 { fputs("\033J\377", prn_stream);
181 skips -= 255;
182 }
183 if ( skips )
184 fprintf(prn_stream, "\033J%c", skips);
185
186 /* If we've printed as far as "limit", then reset "limit"
187 to "last_row" for the final printing pass. */
188 if ( lnum == limit )
189 limit = last_row;
190 skip = 0;
191
192 /* Transpose in blocks of 8 scan lines. */
193 for ( bnum = 0; bnum < bits_per_column; bnum += 8 )
194 { int lcnt = min(8, limit - lnum);
195 byte *inp = in;
196 byte *outp = outl;
197 lcnt = gdev_prn_copy_scan_lines(pdev,
198 lnum, in, lcnt * line_size);
199 if ( lcnt < 0 )
200 { code = lcnt;
201 goto xit;
202 }
203 if ( lcnt < 8 )
204 memset(in + lcnt * line_size, 0,
205 (8 - lcnt) * line_size);
206 for ( ; inp < in_end; inp++, outp += bits_per_column )
207 { gdev_prn_transpose_8x8(inp, line_size,
208 outp, bytes_per_column);
209 }
210 outl++;
211 lnum += lcnt;
212 skip += lcnt;
213 }
214
215 /* Send the bits to the printer. We alternate horizontal
216 skips with the data. The horizontal skips are in units
217 of 1/180 inches, so we look at the data in groups of
218 1 or 2 columns depending on resolution (controlled
219 by skip_unit). */
220 outl = out;
221 do
222 { int count;
223 int n;
224 byte *out_ptr;
225
226 /* First look for blank groups of columns. */
227 while(outl < out_end)
228 { n = count = min(out_end - outl, skip_unit);
229 out_ptr = outl;
230 while ( --count >= 0 )
231 { if ( *out_ptr++ )
232 break;
233 }
234 if ( count >= 0 )
235 break;
236 else
237 outl = out_ptr;
238 }
239 if (outl >= out_end)
240 break;
241 if (outl > out_beg)
242 { count = (outl - out_beg) / skip_unit;
243 fprintf(prn_stream, "\033\\%c%c",
244 count & 0xff, count >> 8);
245 }
246
247 /* Next look for non-blank groups of columns. */
248 out_beg = outl;
249 outl += n;
250 while(outl < out_end)
251 { n = count = min(out_end - outl, skip_unit);
252 out_ptr = outl;
253 while ( --count >= 0 )
254 { if ( *out_ptr++ )
255 break;
256 }
257 if ( count < 0 )
258 break;
259 else
260 outl += n;
261 }
262 count = outl - out_beg;
263 {
264 /* What to transmit is the number of columns in the row.
265 Compare this with the <Esc>|*-command wich expects the
266 total number of bytes in the graphic row! */
267 int count1 = count/bytes_per_column;
268 fprintf(prn_stream, "\033*%c%c%c",
269 mode, count1 & 0xff, count1 >> 8);
270 }
271 fwrite(out_beg, 1, count, prn_stream);
272 out_beg = outl;
273 outl += n;
274 }
275 while ( out_beg < out_end );
276
277 fputc('\r', prn_stream);
278 skip = bits_per_column; /* <CR> only moves to the beginning of the row. */
279 }
280
281 /* Eject the page */
282 xit: fputc(014, prn_stream); /* form feed */
283 fflush(prn_stream);
284 fin: if ( out != 0 )
285 gs_free(pdev->memory, (char *)out, bits_per_column, line_size,
286 "sj48_print_page(out)");
287 if ( in != 0 )
288 gs_free(pdev->memory, (char *)in, 8, line_size, "sj48_print_page(in)");
289 return code;
290 }
291