1 /* Copyright (C) 1989, 2000 artofcode LLC. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 2 of the License, or (at your
6 option) any later version.
7
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along
14 with this program; if not, write to the Free Software Foundation, Inc.,
15 59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 */
17
18 /*$Id: gdevdjet.c,v 1.6.8.1 2003/01/17 00:49:00 giles Exp $ */
19 /* HP LaserJet/DeskJet driver for Ghostscript */
20 #include "gdevprn.h"
21 #include "gdevdljm.h"
22
23 /*
24 * Thanks for various improvements to:
25 * Jim Mayer (mayer@wrc.xerox.com)
26 * Jan-Mark Wams (jms@cs.vu.nl)
27 * Frans van Hoesel (hoesel@chem.rug.nl)
28 * George Cameron (g.cameron@biomed.abdn.ac.uk)
29 * Nick Duffek (nsd@bbc.com)
30 * Thanks for the FS-600 driver to:
31 * Peter Schildmann (peter.schildmann@etechnik.uni-rostock.de)
32 * Thanks for the LJIIID duplex capability to:
33 * PDP (Philip) Brown (phil@3soft-uk.com)
34 * Thanks for the OCE 9050 driver to:
35 * William Bader (wbader@EECS.Lehigh.Edu)
36 * Thanks for the LJ4D duplex capability to:
37 * Les Johnson <les@infolabs.com>
38 */
39
40 /*
41 * You may select a default resolution of 75, 100, 150, 300, or
42 * (LJ4 only) 600 DPI in the makefile, or an actual resolution
43 * on the gs command line.
44 *
45 * If the preprocessor symbol A4 is defined, the default paper size is
46 * the European A4 size; otherwise it is the U.S. letter size (8.5"x11").
47 *
48 * To determine the proper "margin" settings for your printer, see the
49 * file align.ps.
50 */
51
52 /* Define the default, maximum resolutions. */
53 #ifdef X_DPI
54 # define X_DPI2 X_DPI
55 #else
56 # define X_DPI 300
57 # define X_DPI2 600
58 #endif
59 #ifdef Y_DPI
60 # define Y_DPI2 Y_DPI
61 #else
62 # define Y_DPI 300
63 # define Y_DPI2 600
64 #endif
65
66 /*
67 * For all DeskJet Printers:
68 *
69 * Maximum printing width = 2400 dots = 8"
70 * Maximum recommended printing height = 3100 dots = 10 1/3"
71 *
72 * All Deskjets have 1/2" unprintable bottom margin.
73 * The recommendation comes from the HP Software Developer's Guide for
74 * the DeskJet 500, DeskJet PLUS, and DeskJet printers, version C.01.00
75 * of 12/1/90.
76 *
77 * Note that the margins defined just below here apply only to the DeskJet;
78 * the paper size, width and height apply to the LaserJet as well.
79 */
80
81 /* Margins are left, bottom, right, top. */
82 /* from Frans van Hoesel hoesel@rugr86.rug.nl. */
83 /* A4 has a left margin of 1/8 inch and at a printing width of
84 * 8 inch this give a right margin of 0.143. The 0.09 top margin is
85 * not the actual margin - which is 0.07 - but compensates for the
86 * inexact paperlength which is set to 117 10ths.
87 * Somebody should check for letter sized paper. I left it at 0.07".
88 */
89 #define DESKJET_MARGINS_LETTER 0.2, 0.45, 0.3, 0.05
90 #define DESKJET_MARGINS_A4 0.125, 0.5, 0.143, 0.09
91 /* Similar margins for the LaserJet. */
92 /* These are defined in the PCL 5 Technical Reference Manual. */
93 /* Note that for PCL 5 printers, we get the printer to translate the */
94 /* coordinate system: the margins only define the unprintable area. */
95 #define LASERJET_MARGINS_A4 0.167, 0.167, 0.167, 0.167
96 #define LASERJET_MARGINS_LETTER 0.167, 0.167, 0.167, 0.167
97
98 /* See gdevdljm.h for the definitions of the PCL_ features. */
99
100 /* The device descriptors */
101 private dev_proc_open_device(hpjet_open);
102 private dev_proc_close_device(hpjet_close);
103 private dev_proc_print_page_copies(djet_print_page_copies);
104 private dev_proc_print_page_copies(djet500_print_page_copies);
105 private dev_proc_print_page_copies(fs600_print_page_copies);
106 private dev_proc_print_page_copies(ljet_print_page_copies);
107 private dev_proc_print_page_copies(ljetplus_print_page_copies);
108 private dev_proc_print_page_copies(ljet2p_print_page_copies);
109 private dev_proc_print_page_copies(ljet3_print_page_copies);
110 private dev_proc_print_page_copies(ljet3d_print_page_copies);
111 private dev_proc_print_page_copies(ljet4_print_page_copies);
112 private dev_proc_print_page_copies(ljet4d_print_page_copies);
113 private dev_proc_print_page_copies(lp2563_print_page_copies);
114 private dev_proc_print_page_copies(oce9050_print_page_copies);
115
116 private const gx_device_procs prn_hp_procs =
117 prn_params_procs(hpjet_open, gdev_prn_output_page, hpjet_close,
118 gdev_prn_get_params, gdev_prn_put_params);
119
120 const gx_device_printer gs_deskjet_device =
121 prn_device_copies(prn_hp_procs, "deskjet",
122 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
123 X_DPI, Y_DPI,
124 0, 0, 0, 0, /* margins filled in by hpjet_open */
125 1, djet_print_page_copies);
126
127 const gx_device_printer gs_djet500_device =
128 prn_device_copies(prn_hp_procs, "djet500",
129 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
130 X_DPI, Y_DPI,
131 0, 0, 0, 0, /* margins filled in by hpjet_open */
132 1, djet500_print_page_copies);
133
134 const gx_device_printer gs_fs600_device =
135 prn_device_copies(prn_hp_procs, "fs600",
136 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
137 X_DPI2, Y_DPI2,
138 0.23, 0.0, 0.23, 0.04, /* margins */
139 1, fs600_print_page_copies);
140
141 const gx_device_printer gs_laserjet_device =
142 prn_device_copies(prn_hp_procs, "laserjet",
143 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
144 X_DPI, Y_DPI,
145 0.05, 0.25, 0.55, 0.25, /* margins */
146 1, ljet_print_page_copies);
147
148 const gx_device_printer gs_ljetplus_device =
149 prn_device_copies(prn_hp_procs, "ljetplus",
150 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
151 X_DPI, Y_DPI,
152 0.05, 0.25, 0.55, 0.25, /* margins */
153 1, ljetplus_print_page_copies);
154
155 const gx_device_printer gs_ljet2p_device =
156 prn_device_copies(prn_hp_procs, "ljet2p",
157 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
158 X_DPI, Y_DPI,
159 0.20, 0.25, 0.25, 0.25, /* margins */
160 1, ljet2p_print_page_copies);
161
162 const gx_device_printer gs_ljet3_device =
163 prn_device_copies(prn_hp_procs, "ljet3",
164 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
165 X_DPI, Y_DPI,
166 0.20, 0.25, 0.25, 0.25, /* margins */
167 1, ljet3_print_page_copies);
168
169 const gx_device_printer gs_ljet3d_device =
170 prn_device_copies(prn_hp_procs, "ljet3d",
171 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
172 X_DPI, Y_DPI,
173 0.20, 0.25, 0.25, 0.25, /* margins */
174 1, ljet3d_print_page_copies);
175
176 const gx_device_printer gs_ljet4_device =
177 prn_device_copies(prn_hp_procs, "ljet4",
178 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
179 X_DPI2, Y_DPI2,
180 0, 0, 0, 0, /* margins */
181 1, ljet4_print_page_copies);
182
183 const gx_device_printer gs_ljet4d_device =
184 prn_device_copies(prn_hp_procs, "ljet4d",
185 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
186 X_DPI2, Y_DPI2,
187 0, 0, 0, 0, /* margins */
188 1, ljet4d_print_page_copies);
189
190 const gx_device_printer gs_lp2563_device =
191 prn_device_copies(prn_hp_procs, "lp2563",
192 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
193 X_DPI, Y_DPI,
194 0, 0, 0, 0, /* margins */
195 1, lp2563_print_page_copies);
196
197 const gx_device_printer gs_oce9050_device =
198 prn_device_copies(prn_hp_procs, "oce9050",
199 24 * 10, 24 * 10, /* 24 inch roll (can print 32" also) */
200 400, 400, /* 400 dpi */
201 0, 0, 0, 0, /* margins */
202 1, oce9050_print_page_copies);
203
204 /* Open the printer, adjusting the margins if necessary. */
205 private int
hpjet_open(gx_device * pdev)206 hpjet_open(gx_device * pdev)
207 { /* Change the margins if necessary. */
208 gx_device_printer *const ppdev = (gx_device_printer *)pdev;
209 const float *m = 0;
210 bool move_origin = true;
211
212 if (ppdev->printer_procs.print_page_copies == djet_print_page_copies ||
213 ppdev->printer_procs.print_page_copies == djet500_print_page_copies
214 ) {
215 static const float m_a4[4] =
216 {DESKJET_MARGINS_A4};
217 static const float m_letter[4] =
218 {DESKJET_MARGINS_LETTER};
219
220 m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? m_a4 :
221 m_letter);
222 } else if (ppdev->printer_procs.print_page_copies == oce9050_print_page_copies ||
223 ppdev->printer_procs.print_page_copies == lp2563_print_page_copies
224 );
225 else { /* LaserJet */
226 static const float m_a4[4] =
227 {LASERJET_MARGINS_A4};
228 static const float m_letter[4] =
229 {LASERJET_MARGINS_LETTER};
230
231 m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? m_a4 :
232 m_letter);
233 move_origin = false;
234 }
235 if (m != 0)
236 gx_device_set_margins(pdev, m, move_origin);
237 /* If this is a LJIIID, enable Duplex. */
238 if (ppdev->printer_procs.print_page_copies == ljet3d_print_page_copies)
239 ppdev->Duplex = true, ppdev->Duplex_set = 0;
240 if (ppdev->printer_procs.print_page_copies == ljet4d_print_page_copies)
241 ppdev->Duplex = true, ppdev->Duplex_set = 0;
242 return gdev_prn_open(pdev);
243 }
244
245 /* hpjet_close is only here to eject odd numbered pages in duplex mode, */
246 /* and to reset the printer so the ink cartridge doesn't clog up. */
247 private int
hpjet_close(gx_device * pdev)248 hpjet_close(gx_device * pdev)
249 {
250 gx_device_printer *const ppdev = (gx_device_printer *)pdev;
251 int code = gdev_prn_open_printer(pdev, 1);
252
253 if (code < 0)
254 return code;
255 if (ppdev->Duplex_set >= 0 && ppdev->Duplex)
256 fputs("\033&l0H", ppdev->file);
257 fputs("\033E", ppdev->file);
258 return gdev_prn_close(pdev);
259 }
260
261 /* ------ Internal routines ------ */
262
263 /* The DeskJet can compress (mode 2) */
264 private int
djet_print_page_copies(gx_device_printer * pdev,FILE * prn_stream,int num_copies)265 djet_print_page_copies(gx_device_printer * pdev, FILE * prn_stream,
266 int num_copies)
267 {
268 return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
269 300, PCL_DJ_FEATURES,
270 "\033&k1W\033*b2M");
271 }
272 /* The DeskJet500 can compress (modes 2&3) */
273 private int
djet500_print_page_copies(gx_device_printer * pdev,FILE * prn_stream,int num_copies)274 djet500_print_page_copies(gx_device_printer * pdev, FILE * prn_stream,
275 int num_copies)
276 {
277 return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
278 300, PCL_DJ500_FEATURES,
279 "\033&k1W");
280 }
281 /* The Kyocera FS-600 laser printer (and perhaps other printers */
282 /* which use the PeerlessPrint5 firmware) doesn't handle */
283 /* ESC&l#u and ESC&l#Z correctly. */
284 private int
fs600_print_page_copies(gx_device_printer * pdev,FILE * prn_stream,int num_copies)285 fs600_print_page_copies(gx_device_printer * pdev, FILE * prn_stream,
286 int num_copies)
287 {
288 int dots_per_inch = (int)pdev->y_pixels_per_inch;
289 char real_init[60];
290
291 sprintf(real_init, "\033*r0F\033&u%dD", dots_per_inch);
292 return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
293 dots_per_inch, PCL_FS600_FEATURES,
294 real_init);
295 }
296 /* The LaserJet series II can't compress */
297 private int
ljet_print_page_copies(gx_device_printer * pdev,FILE * prn_stream,int num_copies)298 ljet_print_page_copies(gx_device_printer * pdev, FILE * prn_stream,
299 int num_copies)
300 {
301 return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
302 300, PCL_LJ_FEATURES,
303 "\033*b0M");
304 }
305 /* The LaserJet Plus can't compress */
306 private int
ljetplus_print_page_copies(gx_device_printer * pdev,FILE * prn_stream,int num_copies)307 ljetplus_print_page_copies(gx_device_printer * pdev, FILE * prn_stream,
308 int num_copies)
309 {
310 return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
311 300, PCL_LJplus_FEATURES,
312 "\033*b0M");
313 }
314 /* LaserJet series IIp & IId compress (mode 2) */
315 /* but don't support *p+ or *b vertical spacing. */
316 private int
ljet2p_print_page_copies(gx_device_printer * pdev,FILE * prn_stream,int num_copies)317 ljet2p_print_page_copies(gx_device_printer * pdev, FILE * prn_stream,
318 int num_copies)
319 {
320 return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
321 300, PCL_LJ2p_FEATURES,
322 "\033*r0F\033*b2M");
323 }
324 /* All LaserJet series IIIs (III,IIId,IIIp,IIIsi) compress (modes 2&3) */
325 /* They also need their coordinate system translated slightly. */
326 private int
ljet3_print_page_copies(gx_device_printer * pdev,FILE * prn_stream,int num_copies)327 ljet3_print_page_copies(gx_device_printer * pdev, FILE * prn_stream,
328 int num_copies)
329 {
330 return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
331 300, PCL_LJ3_FEATURES,
332 "\033&l-180u36Z\033*r0F");
333 }
334 /* LaserJet IIId is same as LaserJet III, except for duplex */
335 private int
ljet3d_print_page_copies(gx_device_printer * pdev,FILE * prn_stream,int num_copies)336 ljet3d_print_page_copies(gx_device_printer * pdev, FILE * prn_stream,
337 int num_copies)
338 {
339 return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
340 300, PCL_LJ3D_FEATURES,
341 "\033&l-180u36Z\033*r0F");
342 }
343 /* LaserJet 4 series compresses, and it needs a special sequence to */
344 /* allow it to specify coordinates at 600 dpi. */
345 /* It too needs its coordinate system translated slightly. */
346 private int
ljet4_print_page_copies(gx_device_printer * pdev,FILE * prn_stream,int num_copies)347 ljet4_print_page_copies(gx_device_printer * pdev, FILE * prn_stream,
348 int num_copies)
349 {
350 int dots_per_inch = (int)pdev->y_pixels_per_inch;
351 char real_init[60];
352
353 sprintf(real_init, "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch);
354 return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
355 dots_per_inch, PCL_LJ4_FEATURES,
356 real_init);
357 }
358 private int
ljet4d_print_page_copies(gx_device_printer * pdev,FILE * prn_stream,int num_copies)359 ljet4d_print_page_copies(gx_device_printer * pdev, FILE * prn_stream,
360 int num_copies)
361 {
362 int dots_per_inch = (int)pdev->y_pixels_per_inch;
363 char real_init[60];
364
365 sprintf(real_init, "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch);
366 return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
367 dots_per_inch, PCL_LJ4D_FEATURES,
368 real_init);
369 }
370 /* The 2563B line printer can't compress */
371 /* and doesn't support *p+ or *b vertical spacing. */
372 private int
lp2563_print_page_copies(gx_device_printer * pdev,FILE * prn_stream,int num_copies)373 lp2563_print_page_copies(gx_device_printer * pdev, FILE * prn_stream,
374 int num_copies)
375 {
376 return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
377 300, PCL_LP2563B_FEATURES,
378 "\033*b0M");
379 }
380 /* The Oce line printer has TIFF compression */
381 /* and doesn't support *p+ or *b vertical spacing. */
382 private int
oce9050_print_page_copies(gx_device_printer * pdev,FILE * prn_stream,int num_copies)383 oce9050_print_page_copies(gx_device_printer * pdev, FILE * prn_stream,
384 int num_copies)
385 {
386 int code;
387
388 /* Switch to HP_RTL. */
389 fputs("\033%1B", prn_stream); /* Enter HPGL/2 mode */
390 fputs("BP", prn_stream); /* Begin Plot */
391 fputs("IN;", prn_stream); /* Initialize (start plot) */
392 fputs("\033%1A", prn_stream); /* Enter PCL mode */
393
394 code = dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
395 400, PCL_OCE9050_FEATURES,
396 "\033*b3M");
397
398 /* Return to HPGL/2 mode. */
399 fputs("\033%1B", prn_stream); /* Enter HPGL/2 mode */
400 if (code == 0) {
401 fputs("PU", prn_stream); /* Pen Up */
402 fputs("SP0", prn_stream); /* Pen Select */
403 fputs("PG;", prn_stream); /* Advance Full Page */
404 fputs("\033E", prn_stream); /* Reset */
405 }
406 return code;
407 }
408