diff options
Diffstat (limited to 'contrib/gdevadmp.c')
-rw-r--r-- | contrib/gdevadmp.c | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/contrib/gdevadmp.c b/contrib/gdevadmp.c new file mode 100644 index 00000000..d48c0dab --- /dev/null +++ b/contrib/gdevadmp.c @@ -0,0 +1,410 @@ +/* Copyright (C) 2001-2019 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or + implied. + + This software is distributed under license and may not be copied, + modified or distributed except as expressly authorized under the terms + of the license contained in the file LICENSE in this distribution. + + Refer to licensing information at http://www.artifex.com or contact + Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, + CA 94945, U.S.A., +1(415)492-9861, for further information. +*/ + +/* + * Apple DMP / Imagewriter driver + * + * This is a modification of Mark Wedel's Apple DMP and + * Jonathan Luckey's Imagewriter II driver to + * support the Imagewriter LQ's higher resolution (320x216): + * appledmp: 120dpi x 72dpi is still supported (yuck) + * iwlo: 160dpi x 72dpi + * iwhi: 160dpi x 144dpi + * iwlq: 320dpi x 216dpi + * + * This is also my first attempt to work with gs. I have not included the LQ's + * ability to print in colour. Perhaps at a later date I will tackle that. + * + * BTW, to get your Imagewriter LQ serial printer to work with a PC, attach it + * with a nullmodem serial cable. + * + * Scott Barker (barkers@cuug.ab.ca) + */ + +/* + * This is a modification of Mark Wedel's Apple DMP driver to + * support 2 higher resolutions: + * appledmp: 120dpi x 72dpi is still supported (yuck) + * iwlo: 160dpi x 72dpi + * iwhi: 160dpi x 144dpi + * + * The Imagewriter II is a bit odd. In pinfeed mode, it thinks its + * First line is 1 inch from the top of the page. If you set the top + * form so that it starts printing at the top of the page, and print + * to near the bottom, it thinks it has run onto the next page and + * the formfeed will skip a whole page. As a work around, I reverse + * the paper about a 1.5 inches at the end of the page before the + * formfeed to make it think its on the 'right' page. bah. hack! + * + * This is my first attempt to work with gs, so your milage may vary + * + * Jonathan Luckey (luckey@rtfm.mlb.fl.us) + */ + +/* This is a bare bones driver I developed for my apple Dot Matrix Printer. + * This code originally was from the epson driver, but I removed a lot + * of stuff that was not needed. + * + * The Dot Matrix Printer was a predecessor to the apple Imagewriter. Its + * main difference being that it was parallel. + * + * This code should work fine on Imagewriters, as they have a superset + * of commands compared to the DMP printer. + * + * This driver does not produce the smalles output files possible. To + * do that, it should look through the output strings and find repeat + * occurances of characters, and use the escape sequence that allows + * printing repeat sequences. However, as I see it, this the limiting + * factor in printing is not transmission speed to the printer itself, + * but rather, how fast the print head can move. This is assuming the + * printer is set up with a reasonable speed (9600 bps) + * + * WHAT THE CODE DOES AND DOES NOT DO: + * + * To print out images, it sets the printer for unidirection printing + * and 15 cpi (120 dpi). IT sets line feed to 1/9 of an inch (72 dpi). + * When finished, it sets things back to bidirection print, 1/8" line + * feeds, and 12 cpi. There does not appear to be a way to reset + * things to initial values. + * + * This code does not set for 8 bit characters (which is required). It + * also assumes that carriage return/newline is needed, and not just + * carriage return. These are all switch settings on the DMP, and + * I have configured them for 8 bit data and cr only. + * + * You can search for the strings Init and Reset to find the strings + * that set up the printer and clear things when finished, and change + * them to meet your needs. + * + * Also, you need to make sure that the printer daemon (assuming unix) + * doesn't change the data as it is being printed. I have set my + * printcap file (sunos 4.1.1) with the string: + * ms=pass8,-opost + * and it works fine. + * + * Feel free to improve this code if you want. However, please make + * sure that the old DMP will still be supported by any changes. This + * may mean making an imagewriter device, and just copying this file + * to something like gdevimage.c. + * + * The limiting factor of the DMP is the vertical resolution. However, I + * see no way to do anything about this. Horizontal resolution could + * be increased by using 17 cpi (136 dpi). I believe the Imagewriter + * supports 24 cpi (192 dpi). However, the higher dpi, the slower + * the printing. + * + * Dot Matrix Code by Mark Wedel (master@cats.ucsc.edu) + * + * + * As of Oct 2019, maintained by Mike Galatean (contact through https://bugs.ghostscript.com ) + * + */ + +#include "gdevprn.h" + +/* The device descriptors */ +static dev_proc_print_page(dmp_print_page); + +/* Standard DMP device */ +const gx_device_printer far_data gs_appledmp_device = +prn_device(prn_bg_procs, "appledmp", /* The print_page proc is compatible with allowing bg printing */ + 85, /* width_10ths, 8.5" */ + 110, /* height_10ths, 11" */ + 120, 72, /* X_DPI, Y_DPI */ + 0, 0.5, 0.5, 0, /* margins */ + 1, dmp_print_page); + +/* lowrez Imagewriter device */ +const gx_device_printer far_data gs_iwlo_device = +prn_device(prn_bg_procs, "iwlo", /* The print_page proc is compatible with allowing bg printing */ + 85, /* width_10ths, 8.5" */ + 110, /* height_10ths, 11" */ + 160, 72, /* X_DPI, Y_DPI */ + 0, 0.5, 0.5, 0, /* margins */ + 1, dmp_print_page); + +/* hirez Imagewriter device */ +const gx_device_printer far_data gs_iwhi_device = +prn_device(prn_bg_procs, "iwhi", /* The print_page proc is compatible with allowing bg printing */ + 85, /* width_10ths, 8.5" */ + 110, /* height_10ths, 11" */ + 160, 144, /* X_DPI, Y_DPI */ + 0, 0.5, 0.5, 0, /* margins */ + 1, dmp_print_page); + +/* LQ hirez Imagewriter device */ +const gx_device_printer far_data gs_iwlq_device = +prn_device(prn_bg_procs, "iwlq", /* The print_page proc is compatible with allowing bg printing */ + 85, /* width_10ths, 8.5" */ + 110, /* height_10ths, 11" */ + 320, 216, + 0, 0, 0.5, 0, /* margins */ + 1, dmp_print_page); + +/* ------ Internal routines ------ */ + +#define DMP 1 +#define IWLO 2 +#define IWHI 3 +#define IWLQ 4 + +/* Send the page to the printer. */ +static int +dmp_print_page(gx_device_printer *pdev, gp_file *gprn_stream) +{ + int dev_type; + + int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev); + /* Note that in_size is a multiple of 8. */ + int in_size = line_size * 8; + /* FIXME: It would be better if this device used the gp_file and the gp_ API, + * rather than this "back door" approach + */ + FILE *prn_stream = gp_get_file(gprn_stream); + + + byte *buf1 = (byte *)gs_malloc(pdev->memory, in_size, 1, "dmp_print_page(buf1)"); + byte *buf2 = (byte *)gs_malloc(pdev->memory, in_size, 1, "dmp_print_page(buf2)"); + byte *prn = (byte *)gs_malloc(pdev->memory, 3*in_size, 1, "dmp_print_page(prn)"); + + byte *in = buf1; + byte *out = buf2; + int lnum = 0; + + /* Check allocations */ + if ( buf1 == 0 || buf2 == 0 || prn == 0 ) + { + if ( buf1 ) + gs_free(pdev->memory, (char *)buf1, in_size, 1, + "dmp_print_page(buf1)"); + if ( buf2 ) + gs_free(pdev->memory, (char *)buf2, in_size, 1, + "dmp_print_page(buf2)"); + if ( prn ) + gs_free(pdev->memory, (char *)prn, in_size, 1, + "dmp_print_page(prn)"); + return_error(gs_error_VMerror); + } + + if ( pdev->y_pixels_per_inch == 216 ) + dev_type = IWLQ; + else if ( pdev->y_pixels_per_inch == 144 ) + dev_type = IWHI; + else if ( pdev->x_pixels_per_inch == 160 ) + dev_type = IWLO; + else + dev_type = DMP; + + /* Initialize the printer and reset the margins. */ + + fputs("\r\n\033>\033T16", prn_stream); + + switch(dev_type) + { + case IWLQ: + fputs("\033P\033a3", prn_stream); + break; + case IWHI: + case IWLO: + fputs("\033P", prn_stream); + break; + case DMP: + default: + fputs("\033q", prn_stream); + break; + } + + /* Print lines of graphics */ + while ( lnum < pdev->height ) + { + byte *inp; + byte *in_end; + byte *out_end; + int lcnt,ltmp; + int count, passes; + byte *prn_blk, *prn_end, *prn_tmp; + +/* The apple DMP printer seems to be odd in that the bit order on + * each line is reverse what might be expected. Meaning, an + * underscore would be done as a series of 0x80, while on overscore + * would be done as a series of 0x01. So we get each + * scan line in reverse order. + */ + + switch (dev_type) + { + case IWLQ: passes = 3; break; + case IWHI: passes = 2; break; + case IWLO: + case DMP: + default: passes = 1; break; + } + + for (count = 0; count < passes; count++) + { + for (lcnt=0; lcnt<8; lcnt++) + { + switch(dev_type) + { + case IWLQ: ltmp = lcnt + 8*count; break; + case IWHI: ltmp = 2*lcnt + count; break; + case IWLO: + case DMP: + default: ltmp = lcnt; break; + } + + if ((lnum+ltmp)>pdev->height) + memset(in+lcnt*line_size,0,line_size); + else + gdev_prn_copy_scan_lines(pdev, + lnum+ltmp, in + line_size*(7 - lcnt), + line_size); + } + + out_end = out; + inp = in; + in_end = inp + line_size; + for ( ; inp < in_end; inp++, out_end += 8 ) + { + gdev_prn_transpose_8x8(inp, line_size, + out_end, 1); + } + + out_end = out; + + switch (dev_type) + { + case IWLQ: prn_end = prn + count; break; + case IWHI: prn_end = prn + in_size*count; break; + case IWLO: + case DMP: + default: prn_end = prn; break; + } + + while ( (int)(out_end-out) < in_size) + { + *prn_end = *(out_end++); + if ((dev_type) == IWLQ) prn_end += 3; + else prn_end++; + } + } + + switch (dev_type) + { + case IWLQ: + prn_blk = prn; + prn_end = prn_blk + in_size * 3; + while (prn_end > prn && prn_end[-1] == 0 && + prn_end[-2] == 0 && prn_end[-3] == 0) + { + prn_end -= 3; + } + while (prn_blk < prn_end && prn_blk[0] == 0 && + prn_blk[1] == 0 && prn_blk[2] == 0) + { + prn_blk += 3; + } + if (prn_end != prn_blk) + { + if ((prn_blk - prn) > 7) + fprintf(prn_stream,"\033U%04d%c%c%c", + (int)((prn_blk - prn)/3), + 0, 0, 0); + else + prn_blk = prn; + fprintf(prn_stream,"\033C%04d", + (int)((prn_end - prn_blk)/3)); + fwrite(prn_blk, 1, (int)(prn_end - prn_blk), + prn_stream); + } + break; + case IWHI: + for (count = 0; count < 2; count++) + { + prn_blk = prn_tmp = prn + in_size*count; + prn_end = prn_blk + in_size; + while (prn_end > prn_blk && prn_end[-1] == 0) + prn_end--; + while (prn_blk < prn_end && prn_blk[0] == 0) + prn_blk++; + if (prn_end != prn_blk) + { + if ((prn_blk - prn_tmp) > 7) + fprintf(prn_stream, + "\033V%04d%c", + (int)(prn_blk-prn_tmp), + 0); + else + prn_blk = prn_tmp; + fprintf(prn_stream,"\033G%04d", + (int)(prn_end - prn_blk)); + fwrite(prn_blk, 1, + (int)(prn_end - prn_blk), + prn_stream); + } + if (!count) fputs("\033T01\r\n",prn_stream); + } + fputs("\033T15",prn_stream); + break; + case IWLO: + case DMP: + default: + prn_blk = prn; + prn_end = prn_blk + in_size; + while (prn_end > prn_blk && prn_end[-1] == 0) + prn_end--; + while (prn_blk < prn_end && prn_blk[0] == 0) + prn_blk++; + if (prn_end != prn_blk) + { + if ((prn_blk - prn) > 7) + fprintf(prn_stream,"\033V%04d%c", + (int)(prn_blk - prn), 0); + else + prn_blk = prn; + fprintf(prn_stream,"\033G%04d", + (int)(prn_end - prn_blk)); + fwrite(prn_blk, 1, (int)(prn_end - prn_blk), + prn_stream); + } + break; + } + + fputs("\r\n",prn_stream); + + switch (dev_type) + { + case IWLQ: lnum += 24 ; break; + case IWHI: lnum += 16 ; break; + case IWLO: + case DMP: + default: lnum += 8 ; break; + } + } + + /* ImageWriter will skip a whole page if too close to end */ + /* so skip back more than an inch */ + if ( !(dev_type == DMP) ) + fputs("\033T99\n\n\033r\n\n\n\n\033f", prn_stream); + + /* Formfeed and Reset printer */ + fputs("\033T16\f\033<\033B\033E", prn_stream); + fflush(prn_stream); + + gs_free(pdev->memory, (char *)prn, in_size, 1, "dmp_print_page(prn)"); + gs_free(pdev->memory, (char *)buf2, in_size, 1, "dmp_print_page(buf2)"); + gs_free(pdev->memory, (char *)buf1, in_size, 1, "dmp_print_page(buf1)"); + return 0; +} |