1 /* Copyright (C) 1990, 1992 Aladdin Enterprises.  All rights reserved.
2    Distributed by Free Software Foundation, Inc.
3 
4 This file is part of Ghostscript.
5 
6 Ghostscript is distributed in the hope that it will be useful, but
7 WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
8 to anyone for the consequences of using it or for whether it serves any
9 particular purpose or works at all, unless he says so in writing.  Refer
10 to the Ghostscript General Public License for full details.
11 
12 Everyone is granted permission to copy, modify and redistribute
13 Ghostscript, but only under the conditions described in the Ghostscript
14 General Public License.  A copy of this license is supposed to have been
15 given to you along with Ghostscript so you can know your rights and
16 responsibilities.  It should be in a file named COPYING.  Among other
17 things, the copyright notice and this notice must be preserved on all
18 copies.  */
19 
20 /* gdevp201.c */
21 /* NEC PC-PR201 printer driver for Ghostscript */
22 /* modified by m.mori for printers other than pr-201 */
23 /* modified by OkI for hires-98 */
24 /* modified by ASAYAMA Kazunori for Ghostscript version 2.6.1 */
25 #include "gdevprn.h"
26 
27 /* There are NEC PC-PR printer paramaters.
28         MODEL		DEVICE_NAME		X_DPI,Y_DPI		HEAD_PINS	LF_PITCH
29         PC-PR201	"nec160"			160				24			18
30         PC-PR1000	"nec240"			240				40			20
31         PC-PR150	"nec320"			320				48			18
32         PC-PR1000/4	"nec400"			400				60			18
33 */
34 
35 #define WIDTH 80				/* width_10ths, 8" */
36 #define HEIGHT 110				/* height_10ths, 11" */
37 
38 enum{PR201, PR1000, PR150, PR1K4};
39 
40 static dev_proc_print_page(pr201_print_page);
41 
42 /* The device descriptor */
43 gx_device_printer gs_pr201_device =
44   prn_device(prn_std_procs, "pr201",
45         WIDTH,
46         HEIGHT,
47         160,
48         160,
49         0,0,0,0,		/* margins */
50         1, pr201_print_page);
51 
52 gx_device_printer gs_pr1000_device =
53   prn_device(prn_std_procs, "pr1000",
54         WIDTH,
55         HEIGHT,
56         240,
57         240,
58         0,0,0,0,		/* margins */
59         1, pr201_print_page);
60 
61 gx_device_printer gs_pr150_device =
62   prn_device(prn_std_procs, "pr150",
63         WIDTH,
64         HEIGHT,
65         320,
66         320,
67         0,0,0,0,		/* margins */
68         1, pr201_print_page);
69 
70 gx_device_printer gs_pr1000_4_device =
71   prn_device(prn_std_procs, "pr1000_4",
72         WIDTH,
73         HEIGHT,
74         400,
75         400,
76         0,0,0,0,		/* margins */
77         1, pr201_print_page);
78 
79 /* Transpose a block of 8x8 bits */
80 static int
pr201_transpose_8x8(byte * src,int src_step,byte * dst,int dst_step)81 pr201_transpose_8x8(byte *src, int src_step, byte *dst, int dst_step)
82 {
83         byte mask, s, d0, d1, d2, d3, d4, d5, d6, d7;
84         int i;
85 
86         d0 = d1 = d2 = d3 = d4 = d5 = d6 = d7 = 0;
87 
88         for(i=0, mask=0x01; i<8; i++, mask <<= 1) {
89                 s = *src;
90                 if(s & 0x80) d0 |= mask;
91                 if(s & 0x40) d1 |= mask;
92                 if(s & 0x20) d2 |= mask;
93                 if(s & 0x10) d3 |= mask;
94                 if(s & 0x08) d4 |= mask;
95                 if(s & 0x04) d5 |= mask;
96                 if(s & 0x02) d6 |= mask;
97                 if(s & 0x01) d7 |= mask;
98                 src += src_step;
99         }
100 
101         *dst = d0;
102         *(dst += dst_step) = d1;
103         *(dst += dst_step) = d2;
104         *(dst += dst_step) = d3;
105         *(dst += dst_step) = d4;
106         *(dst += dst_step) = d5;
107         *(dst += dst_step) = d6;
108         *(dst += dst_step) = d7;
109 
110         return 0;
111 }
112 
113 static int
check_mode(const char * modename)114 check_mode(const char* modename)
115 {
116         if (!strcmp(modename, "pr201"))
117                 return PR201;
118         else if (!strcmp(modename, "pr1000"))
119                 return PR1000;
120         else if (!strcmp(modename, "pr150"))
121                 return PR150;
122         else
123                 return PR1K4;
124 }
125 
126 /* Send the page to the printer. */
127 static int
pr201_print_page(gx_device_printer * pdev,gp_file * prn_stream)128 pr201_print_page(gx_device_printer *pdev, gp_file *prn_stream)
129 {	int line_size;
130         int height;
131         int bits_per_column;
132         int bytes_per_column;
133         int chunk_size;
134         byte *in, *out;
135         int lnum, skip;
136         int head_pins, lr_pitch, x_dpi;
137         int code = 0;
138         byte mask;
139         int endidx = pdev->width>>3;
140 
141         switch (check_mode(pdev->dname)){
142                 case PR201:
143                         head_pins=24; lr_pitch=18; x_dpi=160; break;
144                 case PR1000:
145                         head_pins=40; lr_pitch=20; x_dpi=240; break;
146                 case PR150:
147                         head_pins=48; lr_pitch=18; x_dpi=320; break;
148                 case PR1K4:
149                 default:
150                         head_pins=60; lr_pitch=18; x_dpi=400; break;
151         }
152 
153         line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
154         height = pdev->height;
155         bits_per_column	 = head_pins;
156         bytes_per_column = bits_per_column / 8;
157         chunk_size = bits_per_column * line_size;
158 
159         in = (byte *)
160                 gs_malloc(pdev->memory->non_gc_memory, bits_per_column, line_size, "pr201_print_page(in)");
161         out = (byte *)
162                 gs_malloc(pdev->memory->non_gc_memory, bits_per_column, line_size, "pr201_print_page(out)");
163         if(in == 0 || out == 0)
164                 return -1;
165 
166         if (pdev->width & 7)
167             mask = ~(255>>(pdev->width & 7));
168         else
169             mask = 255, endidx--;
170 
171         /* Initialize printer */
172         gp_fputs("\033cl", pdev->file);	/* Software Reset */
173         gp_fputs("\033P", pdev->file);	/* Proportional Mode */
174         if (check_mode(pdev->dname)==PR150){
175                 gp_fprintf(pdev->file, "\034d%d.", x_dpi); /* 320 dpi mode. */
176         }
177         gp_fprintf(pdev->file, "\033T%d" , lr_pitch);
178                                 /* 18/120 inch per line */
179 
180         /* Send Data to printer */
181         lnum = 0;
182         skip = 0;
183         while(lnum < height) {
184                 byte *inp, *outp, *out_beg, *out_end, *p;
185                 int x, y, num_lines, size, mod, i;
186 
187                 /* The number of lines to process */
188                 if((num_lines = height - lnum) > bits_per_column)
189                         num_lines = bits_per_column;
190 
191                 /* Copy scan lines */
192                 for (i = 0, p = in; i < num_lines; i++, p += line_size) {
193                     code = gdev_prn_get_bits(pdev, lnum + i, p, NULL);
194                     if (code < 0)
195                         goto error;
196                     p[endidx] &= mask;
197                 }
198 
199                 /* Ensure we have a full stripe of line data */
200                 for (; i < bits_per_column; i++, p += line_size) {
201                     memset(p, 0, line_size);
202                 }
203 
204                 /* Test for all zero */
205                 size = line_size * num_lines;
206                 if(in[0] == 0 &&
207                    !memcmp((char *)in, (char *)in + 1, size - 1)) {
208                         lnum += bits_per_column;
209                         skip ++;
210                         continue;
211                 }
212 
213                 /* Fill zero */
214                 if(num_lines < bits_per_column) {
215                         size = line_size * (bits_per_column - num_lines);
216                         memset(in + line_size * num_lines, 0, size);
217                 }
218                 lnum += bits_per_column;
219 
220                 /* Vertical tab to the appropriate position. */
221                 while(skip > 72) {
222                         gp_fprintf(pdev->file, "\037%c", 16 + 72);
223                         skip -= 72;
224                 }
225                 if(skip > 0) {
226                         gp_fprintf(pdev->file, "\037%c", 16 + skip);
227                 }
228 
229                 /* Transpose in blocks of 8 scan lines. */
230                 for(y = 0; y < bytes_per_column; y ++) {
231                         inp = in + line_size * 8 * y;
232                         outp = out + y;
233                         for(x = 0; x < line_size; x ++) {
234                                 pr201_transpose_8x8(inp, line_size,
235                                                     outp, bytes_per_column);
236                                 inp ++;
237                                 outp += bits_per_column;
238                         }
239                 }
240 
241                 /* Remove trailing 0s. */
242                 out_end = out + chunk_size - 1;
243                 while(out_end >= out) {
244                         if(*out_end)
245                                 break;
246                         out_end --;
247                 }
248                 size = (out_end - out) + 1;
249                 if((mod = size % bytes_per_column) != 0)
250                         out_end += bytes_per_column - mod;
251 
252                 /* Remove leading 0s. */
253                 out_beg = out;
254                 while(out_beg <= out_end) {
255                         if(*out_beg)
256                                 break;
257                         out_beg ++;
258                 }
259                 out_beg -= (out_beg - out) % bytes_per_column;
260 
261                 /* Dot addressing */
262                 gp_fprintf(pdev->file, "\033F%04" PRIdSIZE,
263                            (out_beg - out) / bytes_per_column);
264 
265                 /* Dot graphics */
266                 size = out_end - out_beg + 1;
267                 if (check_mode(pdev->dname)==PR201){
268                         gp_fprintf(pdev->file,"\033J%04d", size / bytes_per_column);
269                 }else{
270                         gp_fprintf(pdev->file,"\034bP,48,%04d.",
271                                    size / bytes_per_column);
272                 }
273                 gp_fwrite(out_beg, size, 1, pdev->file);
274 
275                 /* Carriage Return */
276                 gp_fputc('\r', pdev->file);
277                 skip = 1;
278         }
279 
280         /* Form Feed */
281         gp_fputc('\f',pdev->file);
282         gp_fflush(pdev->file);
283 
284 error:
285         gs_free(pdev->memory->non_gc_memory, (char *)out,
286                 bits_per_column, line_size, "pr201_print_page(out)");
287         gs_free(pdev->memory->non_gc_memory, (char *)in,
288                 bits_per_column, line_size, "pr201_print_page(in)");
289 
290         return code;
291 }
292