home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises. All rights reserved.
- Distributed by Free Software Foundation, Inc.
-
- This file is part of Ghostscript.
-
- Ghostscript is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
- to anyone for the consequences of using it or for whether it serves any
- particular purpose or works at all, unless he says so in writing. Refer
- to the Ghostscript General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- Ghostscript, but only under the conditions described in the Ghostscript
- General Public License. A copy of this license is supposed to have been
- given to you along with Ghostscript so you can know your rights and
- responsibilities. It should be in a file named COPYING. Among other
- things, the copyright notice and this notice must be preserved on all
- copies. */
-
- /* gdevdjet.c */
- /* HP LaserJet/DeskJet driver for Ghostscript */
- #include "gdevprn.h"
-
- #define X_DPI 300
- #define Y_DPI 300
- #define LINE_SIZE ((X_DPI * 85 / 10 + 7) / 8) /* bytes per line */
-
- /* Printer types */
- #define LJ 0
- #define LJ2p 1
- #define LJ3 2
- #define DJ 3
-
- /* The device descriptors */
- private dev_proc_print_page(djet_print_page);
- private dev_proc_print_page(ljet_print_page);
- private dev_proc_print_page(ljet3_prt_page);
- private dev_proc_print_page(ljet2p_prt_page);
-
- gx_device_printer gs_deskjet_device =
- prn_device(prn_std_procs, "deskjet",
- 85, /* width_10ths, 8.5" */
- 110, /* height_10ths, 11" */
- X_DPI, Y_DPI,
- 0.25, 0.25, 0.25, 0.25, /* margins */
- 1, djet_print_page);
-
- gx_device_printer gs_laserjet_device =
- prn_device(prn_std_procs, "laserjet",
- 85, /* width_10ths, 8.5" */
- 110, /* height_10ths, 11" */
- X_DPI, Y_DPI,
- 0.05, 0.25, 0.55, 0.25, /* margins */
- 1, ljet_print_page);
-
- gx_device_printer gs_ljet3_device =
- prn_device(prn_std_procs, "ljet3",
- 85, /* width_10ths, 8.5" */
- 110, /* height_10ths, 11" */
- X_DPI, Y_DPI,
- 0.20, 0.25, 0.25, 0.25, /* margins */
- 1, ljet3_prt_page);
-
- gx_device_printer gs_ljet2p_device =
- prn_device(prn_std_procs, "ljet2p",
- 85, /* width_10ths, 8.5" */
- 110, /* height_10ths, 11" */
- X_DPI, Y_DPI,
- 0.20, 0.25, 0.25, 0.25, /* margins */
- 1, ljet2p_prt_page);
-
- /* Forward references */
- private int mode2compress(P3(char *, char *, char *));
- private int mode3compress(P4(int, char *, char *, char *));
- private int hpjet_print_page(P3(gx_device_printer *, FILE *, int));
-
- /* ------ Internal routines ------ */
-
- /* The DeskJet can compress (mode 2) */
- private int
- djet_print_page(gx_device_printer *pdev, FILE *prn_stream)
- { return hpjet_print_page(pdev, prn_stream, DJ);
- }
- /* The LaserJet series II can't compress */
- private int
- ljet_print_page(gx_device_printer *pdev, FILE *prn_stream)
- { return hpjet_print_page(pdev, prn_stream, LJ);
- }
- /* All LaserJet series IIIs (III,IIId,IIIp,IIIsi) compress (mode 3) */
- private int
- ljet3_prt_page(gx_device_printer *pdev, FILE *prn_stream)
- { return hpjet_print_page(pdev, prn_stream, LJ3);
- }
- /* LaserJet series IIp & IId compress (mode 2) */
- private int
- ljet2p_prt_page(gx_device_printer *pdev, FILE *prn_stream)
- { return hpjet_print_page(pdev, prn_stream, LJ2p);
- }
-
- /* Send the page to the printer. For speed, compress each scan line, */
- /* since computer-to-printer communication time is often a bottleneck. */
- private int
- hpjet_print_page(gx_device_printer *pdev, FILE *prn_stream, int compress)
- { char data[LINE_SIZE*2];
- char out_row[LINE_SIZE*2],
- prev_row[LINE_SIZE*2],
- *out_data;
- int out_count;
- char *skip_pattern;
-
- /* select the most compressed mode available & clear tmp storage */
- switch ( compress )
- {
- case LJ3: /* PCL 5 printers ... mode 3 compression */
- /* put printer in known state */
- fputs("\033E",prn_stream);
-
- /* ends raster graphics to set raster graphics resolution */
- fputs("\033*rB", prn_stream);
-
- /* set raster graphics resolution -- 300 dpi */
- fputs("\033*t300R", prn_stream);
- /* move to top left of page & set current position */
- fputs("\033*r0f0A", prn_stream);
- fputs("\033&l0E", prn_stream);
- fputs("\033&l-185U", prn_stream);
- fputs("\033*p0x0Y", prn_stream);
- fputs("\033*b3M", prn_stream);
- memset( out_row,0,LINE_SIZE*2 );
- memset( prev_row,0,LINE_SIZE*2 );
- skip_pattern = "\033*b%dY";
- break;
- case LJ2p: /* PCL 4 printers ... mode 2 compression */
- /* put printer in known state */
- fputs("\033E",prn_stream);
-
- /* ends raster graphics to set raster graphics resolution */
- fputs("\033*rB", prn_stream);
-
- /* set raster graphics resolution -- 300 dpi */
- fputs("\033*t300R", prn_stream);
- /* move to top left of page & set current position */
- fputs("\033*r0f0A", prn_stream);
- fputs("\033&l0E", prn_stream);
- fputs("\033&l-185U", prn_stream);
- fputs("\033*p0x0Y", prn_stream);
- fputs("\033*b2M", prn_stream);
- memset( out_row,0,LINE_SIZE*2 );
- skip_pattern = "\033*b%dY";
- break;
- case DJ: /* almost PCL 4 printers ... mode 2 compression */
- /* ends raster graphics to set raster graphics resolution */
- fputs("\033*rB", prn_stream);
-
- /* set raster graphics resolution -- 300 dpi */
- fputs("\033*t300R", prn_stream);
- /* move to top left of page & set current position */
- fputs("\033*p0x0Y", prn_stream);
- fputs("\033*r0A", prn_stream);
- fputs("\033*b2M", prn_stream);
- memset( out_row,0,LINE_SIZE*2 );
- skip_pattern = "\033*b%dY";
- break;
- default: /* LaserJet PCL 3 printers support un-compressed images */
- /* put printer in known state */
- fputs("\033E",prn_stream);
-
- /* ends raster graphics to set raster graphics resolution */
- fputs("\033*rB", prn_stream);
-
- /* set raster graphics resolution -- 300 dpi */
- fputs("\033*t300R", prn_stream);
- /* move to top left of page & set current position */
- fputs("\033*r0A", prn_stream);
- fputs("\033&l0E", prn_stream);
- fputs("\033*p0x0Y", prn_stream);
- fputs("\033*b0M", prn_stream);
- memset( out_row,0,LINE_SIZE*2 );
- skip_pattern = "\033*p+%dY";
- break;
- }
-
-
- /* Send each scan line in turn */
- { int lnum;
- int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
- int num_blank_lines = 0;
- byte rmask = (byte)(0xff << (-pdev->width & 7));
- /* look for top margin white space... You would think that
- the normal (raster) white space mechanism would work... it
- doesn't... Sometimes PCL printers are brain-dead */
- for ( lnum = 0; lnum < pdev->height; lnum++ )
- { char *end_data = data + LINE_SIZE;
- gdev_prn_copy_scan_lines(pdev, lnum,
- (byte *)data, line_size);
- /* Mask off 1-bits beyond the line width. */
- end_data[-1] &= rmask;
- /* Remove trailing 0s. */
- while ( end_data > data && end_data[-1] == 0 )
- end_data--;
- if ( end_data == data )
- /* Blank line */
- num_blank_lines++;
- else
- break;
- }
- /* Skip blank lines if any */
- if ( num_blank_lines > 0 )
- { /* move down from current position */
- fprintf(prn_stream,"\033*p+%dY", num_blank_lines);
- num_blank_lines = 0;
- }
- /* transfer raster graphics */
- for ( ; lnum < pdev->height; lnum++ )
- { char *end_data = data + LINE_SIZE;
- gdev_prn_copy_scan_lines(pdev, lnum,
- (byte *)data, line_size);
- /* Mask off 1-bits beyond the line width. */
- end_data[-1] &= rmask;
- /* Remove trailing 0s. */
- while ( end_data > data && end_data[-1] == 0 )
- end_data--;
- if ( end_data == data )
- { /* Blank line */
- num_blank_lines++;
- continue;
- }
- switch (compress)
- {
- case LJ3:
- out_data = out_row;
- out_count = mode3compress(line_size, data,
- prev_row,out_row);
- break;
- case DJ:
- case LJ2p:
- out_data = out_row;
- out_count = mode2compress(data, end_data,
- out_row);
- break;
- default:
- out_data = data;
- out_count = end_data - data;
- }
- /* Skip blank lines if any */
- if ( num_blank_lines > 0 )
- { /* move down from current position */
- fprintf(prn_stream, skip_pattern,
- num_blank_lines);
- num_blank_lines = 0;
- }
- /* transfer raster graphics */
- fprintf(prn_stream, "\033*b%dW", out_count);
- /* send the row */
- fwrite(out_data, sizeof(char), out_count,
- prn_stream);
- }
- }
-
- /* end raster graphics */
- fputs("\033*rB", prn_stream);
-
- /* eject page */
- fputs("\033&l0H", prn_stream);
-
- return 0;
- }
-
-
- /* Mode 2 Row compression routine for the HP DeskJet & LaserJet IIp. */
- /* Compresses data from row up to end_row, storing the result */
- /* starting at compressed. Returns the number of bytes stored. */
- /* Runs of K<=127 literal bytes are encoded as K-1 followed by */
- /* the bytes; runs of 2<=K<=127 identical bytes are encoded as */
- /* 257-K followed by the byte. */
- /* In the worst case, the result is N+(N/127)+1 bytes long, */
- /* where N is the original byte count (end_row - row). */
- private int
- mode2compress(char *row, char *end_row, char *compressed)
- { register char *i_exam = row; /* byte being examined in the row to compress */
- char *stop_exam = end_row - 4; /* stop scanning for similar bytes here */
- register char *cptr = compressed; /* output pointer into compressed bytes */
-
- while ( i_exam < end_row )
- { /* Search ahead in the input looking for a run */
- /* of at least 4 identical bytes. */
- char *i_compr = i_exam;
- char *i_next; /* end of run */
- char byte_value;
- while ( i_exam <= stop_exam &&
- ((byte_value = *i_exam) != i_exam[1] ||
- byte_value != i_exam[2] ||
- byte_value != i_exam[3]) )
- i_exam++;
-
- /* Find out how long the run is */
- if ( i_exam > stop_exam ) /* no run */
- i_next = i_exam = end_row;
- else
- { i_next = i_exam + 4;
- while ( i_next < end_row && *i_next == byte_value )
- i_next++;
- }
-
- /* Now [i_compr..i_exam) should be encoded as dissimilar, */
- /* and [i_exam..i_next) should be encoded as similar. */
- /* Note that either of these ranges may be empty. */
-
- while ( i_compr < i_exam )
- { /* Encode up to 127 dissimilar bytes */
- int count = i_exam - i_compr;
- if ( count > 127 ) count = 127;
- *cptr++ = count - 1;
- while ( count > 0 )
- { *cptr++ = *i_compr++;
- count--;
- }
- }
-
- while ( i_exam < i_next )
- { /* Encode up to 127 similar bytes */
- int count = i_next - i_exam;
- if ( count > 127 ) count = 127;
- *cptr++ = 1 - count;
- *cptr++ = byte_value;
- i_exam += count;
- }
- }
- return (cptr - compressed);
- }
-
- /* Row compression routine for the HP LaserJet III family. */
- /* Compresses data from row up to end_row, storing the result */
- /* starting at compressed. Returns the number of bytes stored. */
- private int
- mode3compress(int bytecount, char *current, char *previous, char *compressed)
- { register int j;
- int l,
- cap=0,
- outbytes=0,
- byteschanged=0,
- offset,loffset,loffset1;
- char *ptmp;
- static char bittab[9] =
- { 0x00,0x00,0x20,0x40,0x60,0x80,0xa0,0xc0,0xe0 };
-
- for( j = 0; j < bytecount; j++ )
- { if (*previous == *current)
- { *previous++ = *current++;
- if (byteschanged) /* 1st non-change after at least one change */
- { offset = j - cap - byteschanged;
- cap = j;
- loffset = offset - 31;
- if ( offset > 30 )
- offset = 31;
- loffset1 = loffset - 255;
- if ( loffset > 254 )
- loffset = 255;
- /* setup byte1 */
- *compressed++ = bittab[byteschanged] | offset;
- outbytes++;
- if (loffset >= 0)
- { *compressed++ = (char)loffset;
- loffset = 0;
- outbytes++;
- if (loffset1 >= 0)
- { *compressed++ = (char)loffset1;
- loffset1 = 0;
- outbytes++;
- }
- }
- ptmp = current - byteschanged -1;
- for (l=0;l < byteschanged;l++)
- *compressed++ = *ptmp++;
- outbytes = outbytes + byteschanged;
- byteschanged = 0;
- }
- }
- else
- { *previous++ = *current++;
- if (++byteschanged == 8)
- { offset = j - cap - 7;
- cap = j + 1;
- loffset = offset - 31;
- if (offset > 30)
- offset = 31;
- loffset1 = loffset - 255;
- if (loffset > 254)
- loffset = 255;
- *compressed++ = (char)(0xE0 | offset);
- outbytes++;
- if (loffset >= 0)
- { *compressed++ = (char)loffset;
- loffset = 0;
- outbytes++;
- if (loffset1 >= 0)
- { *compressed++ = (char)loffset1;
- loffset1 = 0;
- outbytes++;
- }
- }
- ptmp = current - byteschanged;
- for (l=0;l < byteschanged;l++)
- *compressed++ = *ptmp++;
- outbytes = outbytes + byteschanged;
- byteschanged = 0;
- }
- }
- }
- if (byteschanged)
- { offset = j - cap - byteschanged;
- loffset = offset - 31;
- if (offset > 30)
- offset = 31;
- loffset1 = loffset - 255;
- if (loffset > 254)
- loffset = 255;
- *compressed++ = bittab[byteschanged] | offset;
- outbytes++;
- if (loffset >= 0)
- { *compressed++ = (char)loffset;
- loffset = 0;
- outbytes++;
- if (loffset1 >= 0)
- { *compressed++ = (char)loffset1;
- loffset1 = 0;
- outbytes++;
- }
- }
- ptmp = current - byteschanged;
- for (l=0;l < byteschanged;l++)
- *compressed++ = *ptmp++;
- outbytes = outbytes + byteschanged;
-
- }
-
- return(outbytes);
-
- }
-