1 /* Copyright (C) 1998 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: gdevl31s.c,v 1.5 2004/09/02 21:30:53 giles Exp $ */ 18 /* 19 * H-P LaserJet 3100 driver 20 * 21 * This is a driver for use with the H-P LaserJet 3100 Software. 22 * It requires installed H-P LaserJet 3100 Software to print. 23 * It can be used with smbclient to print from an UNIX box 24 * to a LaserJet 3100 printer attached to a MS-Windows box. 25 * 26 * Written by Ulrich Schmid, uschmid@mail.hh.provi.de. 27 */ 28 29 #include "gdevprn.h" 30 #include "gdevmeds.h" 31 32 #define XCORRECTION 0.11 33 #define YCORRECTION 0.12 34 35 /* order matters! 0 1 2 3 4 5 6 7 8 */ 36 const char *media[10] = {"a4", "letter", "legal", "com10", "c5", "dl", "b5", "monarch", "executive", 0}; 37 const int height[2][10] = {{3447, 3240, 4140, 5587, 2644, 5083, 2975, 4387, 3090, 0}, 38 {6894, 6480, 8280, 11167, 5288, 10159, 5950, 8767, 6180, 0}}; 39 const int width[2] = {2528, 40 5056}; 41 #define LARGEST_MEDIUM 2 /* legal */ 42 43 /* These codes correspond to sequences of pixels with the same color. 44 * After the code for a sequence < 64 pixels the color changes. 45 * After the code for a sequence with 64 pixels the previous color continues. */ 46 private struct { 47 uint bits; 48 uint length; /* number of valid bits */ 49 } code[2][65] = 50 /* White */ 51 {{{0x0ac, 8}, {0x038, 6}, {0x00e, 4}, {0x001, 4}, {0x00d, 4}, {0x003, 4}, {0x007, 4}, {0x00f, 4}, 52 {0x019, 5}, {0x005, 5}, {0x01c, 5}, {0x002, 5}, {0x004, 6}, {0x030, 6}, {0x00b, 6}, {0x02b, 6}, 53 {0x015, 6}, {0x035, 6}, {0x072, 7}, {0x018, 7}, {0x008, 7}, {0x074, 7}, {0x060, 7}, {0x010, 7}, 54 {0x00a, 7}, {0x06a, 7}, {0x064, 7}, {0x012, 7}, {0x00c, 7}, {0x040, 8}, {0x0c0, 8}, {0x058, 8}, 55 {0x0d8, 8}, {0x048, 8}, {0x0c8, 8}, {0x028, 8}, {0x0a8, 8}, {0x068, 8}, {0x0e8, 8}, {0x014, 8}, 56 {0x094, 8}, {0x054, 8}, {0x0d4, 8}, {0x034, 8}, {0x0b4, 8}, {0x020, 8}, {0x0a0, 8}, {0x050, 8}, 57 {0x0d0, 8}, {0x04a, 8}, {0x0ca, 8}, {0x02a, 8}, {0x0aa, 8}, {0x024, 8}, {0x0a4, 8}, {0x01a, 8}, 58 {0x09a, 8}, {0x05a, 8}, {0x0da, 8}, {0x052, 8}, {0x0d2, 8}, {0x04c, 8}, {0x0cc, 8}, {0x02c, 8}, 59 {0x01b, 5}}, 60 /* Black */ 61 {{0x3b0, 10}, {0x002, 3}, {0x003, 2}, {0x001, 2}, {0x006, 3}, {0x00c, 4}, {0x004, 4}, {0x018, 5}, 62 {0x028, 6}, {0x008, 6}, {0x010, 7}, {0x050, 7}, {0x070, 7}, {0x020, 8}, {0x0e0, 8}, {0x030, 9}, 63 {0x3a0, 10}, {0x060, 10}, {0x040, 10}, {0x730, 11}, {0x0b0, 11}, {0x1b0, 11}, {0x760, 11}, {0x0a0, 11}, 64 {0x740, 11}, {0x0c0, 11}, {0x530, 12}, {0xd30, 12}, {0x330, 12}, {0xb30, 12}, {0x160, 12}, {0x960, 12}, 65 {0x560, 12}, {0xd60, 12}, {0x4b0, 12}, {0xcb0, 12}, {0x2b0, 12}, {0xab0, 12}, {0x6b0, 12}, {0xeb0, 12}, 66 {0x360, 12}, {0xb60, 12}, {0x5b0, 12}, {0xdb0, 12}, {0x2a0, 12}, {0xaa0, 12}, {0x6a0, 12}, {0xea0, 12}, 67 {0x260, 12}, {0xa60, 12}, {0x4a0, 12}, {0xca0, 12}, {0x240, 12}, {0xec0, 12}, {0x1c0, 12}, {0xe40, 12}, 68 {0x140, 12}, {0x1a0, 12}, {0x9a0, 12}, {0xd40, 12}, {0x340, 12}, {0x5a0, 12}, {0x660, 12}, {0xe60, 12}, 69 {0x3c0, 10}}}; 70 71 /* Define the default, maximum resolutions. */ 72 #ifndef X_DPI 73 # define X_DPI 600 74 #endif 75 #ifndef Y_DPI 76 # define Y_DPI 600 77 #endif 78 79 /* The device descriptors */ 80 private dev_proc_print_page_copies(lj3100sw_print_page_copies); 81 private dev_proc_close_device(lj3100sw_close); 82 83 private gx_device_procs prn_lj3100sw_procs = 84 prn_params_procs(gdev_prn_open, gdev_prn_output_page, lj3100sw_close, 85 gdev_prn_get_params, gdev_prn_put_params); 86 87 /* workaround to emulate the missing prn_device_margins_copies macro */ 88 #define gx_default_print_page_copies lj3100sw_print_page_copies 89 gx_device_printer far_data gs_lj3100sw_device = 90 prn_device_margins/*_copies*/(prn_lj3100sw_procs, "lj3100sw", 91 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, 92 X_DPI, Y_DPI, 93 XCORRECTION, YCORRECTION, 94 0.25, 0.2, 0.25, 0.2, 95 1, 0 /* lj3100sw_print_page_copies */); 96 #undef gx_default_print_page_copies 97 98 #define ppdev ((gx_device_printer *)pdev) 99 100 #define BUFFERSIZE 0x1000 101 102 private void 103 lj3100sw_output_section_header(FILE *prn_stream, int type, int arg1, int arg2) 104 { 105 fputc(type & 0xff, prn_stream); 106 fputc(type >> 8 & 0xff, prn_stream); 107 fputc(arg1 & 0xff, prn_stream); 108 fputc(arg1 >> 8 & 0xff, prn_stream); 109 fputc(arg2 & 0xff, prn_stream); 110 fputc(arg2 >> 8 & 0xff, prn_stream); 111 } 112 113 private void 114 lj3100sw_flush_buffer(FILE *prn_stream, char *buffer, char **pptr) 115 { 116 int size = *pptr - buffer; 117 if (size) { 118 lj3100sw_output_section_header(prn_stream, 0, size, 0); 119 fwrite(buffer, 1, size, prn_stream); 120 *pptr = buffer; 121 } 122 } 123 124 private void 125 lj3100sw_output_data_byte(FILE *prn_stream, char *buffer, char **pptr, int val) 126 { 127 if (*pptr >= buffer + BUFFERSIZE) 128 lj3100sw_flush_buffer(prn_stream, buffer, pptr); 129 *(*pptr)++ = val; 130 } 131 132 private void 133 lj3100sw_output_repeated_data_bytes(FILE *prn_stream, char *buffer, char **pptr, int val, int num) 134 { 135 int size; 136 while (num) { 137 if (*pptr >= buffer + BUFFERSIZE) 138 lj3100sw_flush_buffer(prn_stream, buffer, pptr); 139 size = min(num, buffer + BUFFERSIZE - *pptr); 140 memset(*pptr, val, size); 141 *pptr += size; 142 num -= size; 143 } 144 } 145 146 private void 147 lj3100sw_output_newline(FILE *prn_stream, char *buffer, char **pptr) 148 { 149 lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0); 150 lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0); 151 lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x80); 152 } 153 154 private void 155 lj3100sw_output_empty_line(FILE *prn_stream, char *buffer, char **pptr, bool high_resolution) 156 { 157 if (high_resolution) { 158 lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x80); 159 lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x0f); 160 lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x78); 161 lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0xac); 162 } else { 163 lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x80); 164 lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x87); 165 lj3100sw_output_data_byte(prn_stream, buffer, pptr, 0x0d); 166 } 167 } 168 169 private int 170 lj3100sw_print_page_copies(gx_device_printer *pdev, FILE *prn_stream, int num_copies /* ignored */) 171 { 172 int i, j; 173 char buffer[BUFFERSIZE], *ptr = buffer; 174 int medium_index = select_medium(pdev, media, LARGEST_MEDIUM); 175 bool high_resolution = (pdev->x_pixels_per_inch > 300); 176 int printer_height = height[high_resolution ? 1 : 0][medium_index]; 177 int printer_width = width[high_resolution ? 1 : 0]; 178 int paper_height = pdev->height; 179 int paper_width = pdev->width; 180 int line_size = gdev_prn_raster(pdev); 181 gs_memory_t *mem = pdev->memory; 182 byte *in = (byte *)gs_malloc(mem, line_size, 1, "lj3100sw_print_page"); 183 byte *data; 184 if (in == 0) 185 return_error(gs_error_VMerror); 186 if (gdev_prn_file_is_new(pdev)) { 187 lj3100sw_output_section_header(prn_stream, 1, 0, 0); 188 lj3100sw_output_repeated_data_bytes(prn_stream, buffer, &ptr, 0x1b, 12); 189 ptr += sprintf(ptr, "\r\nBD"); 190 lj3100sw_output_repeated_data_bytes(prn_stream, buffer, &ptr, 0, 5520); 191 ptr += sprintf(ptr, "%s\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n", 192 "NJ", 193 "PQ", -1, 194 "RE", high_resolution ? 6 : 2, 195 "SL", printer_width, 196 "LM", 0, 197 "PS", medium_index, 198 "PC", 0); 199 lj3100sw_flush_buffer(prn_stream, buffer, &ptr); 200 } 201 202 lj3100sw_output_section_header(prn_stream, 3, ppdev->NumCopies, 0); 203 ptr += sprintf(ptr, "%s %d\r\n%s\r\n", 204 "CM", 1, 205 "PD"); 206 *ptr++ = 0; 207 lj3100sw_output_newline(prn_stream, buffer, &ptr); 208 209 for (i = 0; i < printer_height; i++) { 210 if (i < paper_height) { 211 int color = 0; /* white */ 212 int count = 0; 213 int bit_index = 0; 214 uint tmp = 0; 215 gdev_prn_get_bits(pdev, i, in, &data); 216 for (j = 0; j <= printer_width; j++) { 217 int xoffset = (printer_width - paper_width) / 2; 218 int newcolor = 0; 219 if (j >= xoffset && j < xoffset + paper_width) 220 newcolor = (data[(j - xoffset) / 8] >> (7 - (j - xoffset) % 8)) & 1; 221 if (j == printer_width) 222 newcolor = !color; /* force output */ 223 if (newcolor == color) 224 count++; 225 else if (count == printer_width && color == 0) /* implies j == printer_width */ 226 lj3100sw_output_empty_line(prn_stream, buffer, &ptr, high_resolution); 227 else /* print a sequence of pixels with a uniform color */ 228 while (newcolor != color) { 229 int size = min(count, 64); 230 tmp |= code[color][size].bits << bit_index; 231 bit_index += code[color][size].length; 232 while (bit_index >= 8) { 233 lj3100sw_output_data_byte(prn_stream, buffer, &ptr, tmp & 0xff); 234 tmp >>= 8; 235 bit_index -= 8; 236 } 237 if (size == 64) 238 count -= 64; 239 else { 240 color = newcolor; 241 count = 1; 242 } 243 } 244 } 245 if (bit_index) 246 lj3100sw_output_data_byte(prn_stream, buffer, &ptr, tmp & 0xff); 247 } 248 else 249 lj3100sw_output_empty_line(prn_stream, buffer, &ptr, high_resolution); 250 lj3100sw_output_newline(prn_stream, buffer, &ptr); 251 } 252 253 for (i = 0; i < 3; i++ ) { 254 lj3100sw_output_data_byte(prn_stream, buffer, &ptr, 0x00); 255 lj3100sw_output_data_byte(prn_stream, buffer, &ptr, 0x08); 256 lj3100sw_output_data_byte(prn_stream, buffer, &ptr, 0x80); 257 } 258 lj3100sw_output_repeated_data_bytes(prn_stream, buffer, &ptr, 0, 520); 259 lj3100sw_flush_buffer(prn_stream, buffer, &ptr); 260 261 lj3100sw_output_section_header(prn_stream, 4, 0, 0); 262 for (i = 0; i < 4 * ppdev->NumCopies; i++) 263 lj3100sw_output_section_header(prn_stream, 54, 0, 0); 264 265 gs_free(mem, (char *)in, line_size, 1, "lj3100sw_print_page"); 266 return 0; 267 } 268 269 private int 270 lj3100sw_close(gx_device *pdev) 271 { 272 int i; 273 FILE *prn_stream = ((gx_device_printer *)pdev)->file; 274 275 lj3100sw_output_section_header(prn_stream, 0, 4, 0); 276 fputs("XX\r\n", prn_stream); 277 for (i = 0; i < 4 * ppdev->NumCopies; i++) 278 lj3100sw_output_section_header(prn_stream, 54, 0, 0); 279 lj3100sw_output_section_header(prn_stream, 2, 0, 0); 280 281 return gdev_prn_close(pdev); 282 } 283