home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1990 Commodore-Amiga, Inc.
- *
- * This example is provided in electronic form by Commodore-Amiga, Inc. for
- * use with the 1.3 revisions of the Addison-Wesley Amiga reference manuals.
- * The 1.3 Addison-Wesley Amiga Reference Manual series contains additional
- * information on the correct usage of the techniques and operating system
- * functions presented in this example. The source and executable code of
- * this example may only be distributed in free electronic form, via bulletin
- * board or as part of a fully non-commercial and freely redistributable
- * diskette. Both the source and executable code (including comments) must
- * be included, without modification, in any copy. This example may not be
- * published in printed form or distributed with any commercial product.
- * However, the programming techniques and support routines set forth in
- * this example may be used in the development of original executable
- * software products for Commodore Amiga computers.
- * All other rights reserved.
- * This example is provided "as-is" and is subject to change; no warranties
- * are made. All use is at your own risk. No liability or responsibility
- * is assumed.
- */
-
- #include <exec/types.h>
- #include <exec/nodes.h>
- #include <exec/lists.h>
- #include <exec/memory.h>
- #include <devices/printer.h>
- #include <devices/prtbase.h>
-
- #define NUMSTARTCMD 7 /* # of cmd bytes before binary data */
- #define NUMENDCMD 0 /* # of cmd bytes after binary data */
- #define NUMTOTALCMD (NUMSTARTCMD + NUMENDCMD) /* total of above */
- #define NUMLFCMD 9 /* # of cmd bytes for linefeed */
- #define MAXCOLORBUFS 16 /* max # of color buffers */
-
- #define RLEMAX 136
- #define RLENUMSTARTCMD 3 /* # of cmd bytes before binary data */
- #define RLENUMENDCMD 1 /* # of cmd bytes after binary data */
- #define RLENUMTOTALCMD (RLENUMSTARTCMD + RLENUMENDCMD) /* total of above */
- #define RLESAFETY 10 /* extra room for overwrites */
-
- #define PMODE 15 /* index into StartBuf for print mode */
- #define STARTLEN 16 /* length of start buffer */
-
- extern UBYTE MargBuf[];
-
- Render(ct, x, y, status)
- long ct, x, y, status;
- {
- extern void *AllocMem(), FreeMem();
- extern struct PrinterData *PD;
- extern struct PrinterExtendedData *PED;
-
- static UWORD RowSize, ColorSize, BufSize, TotalBufSize, dataoffset;
- static UWORD colors[MAXCOLORBUFS]; /* color indexes */
- static UWORD color_order[] =
- {0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7, 12, 13, 14, 15};
- static UWORD huns, tens, ones; /* used to program buffer size */
- static UWORD NumColorBufs; /* actually # of color buffers */
- /*
- 00-02 \033F0 set 10 cpi
- 03-07 \033l05\r set left margin to .5 inches
- 09-12 \033r95\r set right margin to 9.5 inches
- 13-15 \033we select standard (e) or
- enhanced (f) graphics mode.
- */
- static UBYTE stdmode, StartBuf[STARTLEN] =
- {0x1b,'F','0',0x1b,'l','0','5',0x0d,0x1b,'r','9','5',0x0d,0x1b,'w','e'};
-
- UBYTE *ptr, *ptrstart;
- int i, err;
-
- static UWORD RLEBufSize, rledataoffset;
- static UBYTE *RLEBuf;
- UBYTE *rleptrstart, *rleptr, *rleptrmark, rledata;
- int rlecount, j;
-
- switch(status) {
- case 0 : /* Master Initialization */
- /*
- ct - pointer to IODRPReq structure.
- x - width of printed picture in pixels.
- y - height of printed picture in pixels.
- */
- /* calc # of bytes of row data */
- RowSize = (x + 7) / 8;
- /* size of each color buf */
- ColorSize = RowSize + NUMTOTALCMD;
- huns = RowSize / 100;
- tens = (RowSize - huns * 100) / 10;
- ones = RowSize % 10;
- if (PD->pd_Preferences.PrintShade == SHADE_COLOR) {
- NumColorBufs = MAXCOLORBUFS;
- }
- else {
- NumColorBufs = 4;
- }
- BufSize = ColorSize * NumColorBufs + NUMLFCMD;
- TotalBufSize = BufSize * 2;
- RLEBufSize = BufSize + RLESAFETY;
- TotalBufSize += RLEBufSize * 2;
- /*
- My color order: B, Y, M, C
- Xerox's color order: B, M, Y, C
- */
- for (i=0; i<NumColorBufs; i++) {
- colors[color_order[i]] = ColorSize * i;
- }
- PD->pd_PrintBuf = AllocMem(TotalBufSize, MEMF_PUBLIC);
- if (PD->pd_PrintBuf == NULL) {
- err = PDERR_BUFFERMEMORY; /* no mem */
- }
- else {
- dataoffset = NUMSTARTCMD;
- err = (*(PD->pd_PWrite))(StartBuf, STARTLEN);
- RLEBuf = &PD->pd_PrintBuf[BufSize * 2];
- rledataoffset = RLENUMSTARTCMD;
- }
- break;
-
- case 1 : /* Scale, Dither and Render */
- /*
- ct - pointer to PrtInfo structure.
- x - 0.
- y - row # (0 to Height - 1).
- */
- Transfer(ct, y, &PD->pd_PrintBuf[dataoffset], colors);
- err = PDERR_NOERR; /* all ok */
- break;
-
- case 2 : /* Dump Buffer to Printer */
- /*
- ct - 0.
- x - 0.
- y - # of rows sent (1 to NumRows).
- */
- /* Run-Length Encode (rle) the data */
- rleptrstart = rleptr =
- &RLEBuf[rledataoffset - RLENUMSTARTCMD];
- /* ptr to data */
- ptrstart = &PD->pd_PrintBuf[dataoffset];
- for (ct=0; ct<NumColorBufs;
- ct++, ptrstart += ColorSize) {
- /* save start posn for this color */
- rleptrmark = rleptr;
- *rleptr++ = 27; /* rle start cmd */
- *rleptr++ = 'h';
- *rleptr++ = ct | '0'; /* color code */
- ptr = ptrstart; /* get ptr to bytes to rle */
- j = RowSize - 1; /* # of bytes left to rle */
- do {
- /* first do repeating bytes */
- /* get goal (repeating) byte */
- rledata = *ptr++;
- /* this many repetitions left to go*/
- i = RLEMAX - 1;
- /* while repeating and not too many
- and more to do */
- while (*ptr == rledata && i > 0 &&
- j > 0) {
- i--; /* one more rle byte */
- /* advance ptr to next byte */
- ptr++;
- /* one less byte to look at */
- j--;
- }
- /* calc repeating byte count */
- if ((rlecount = RLEMAX - i) == 1) {
- /* if only 1 then no repeat */
- rlecount = 0;
- }
- else {
- /* dont forget the goal byte */
- j--;
- }
- /* if there was repeat data */
- if (rlecount != 0) {
- /* save repeat count */
- *rleptr++ = rlecount;
- /* save repeat byte */
- *rleptr++ = rledata;
- /* get non-repeat goal byte */
- rledata = *ptr++;
- }
- /* now do non-repeating data */
- /* no non-repeating bytes yet */
- rlecount = 0;
- if (*ptr != rledata && j >= 0) {
- /* non-repeat data follows */
- *rleptr++ = 0x00;
- }
- /* while non-repeating and more to do */
- while (*ptr != rledata && j >= 0) {
- /* save byte */
- *rleptr++ = rledata;
- /* if byte same as terminator */
- if (rledata == 0xfe) {
- /* save byte (again) */
- *rleptr++ = rledata;
- }
- /* one more non-repeat byte */
- rlecount++;
- /* get goal byte */
- rledata = *ptr++;
- /* one less byte to look at */
- j--;
- }
- if (rlecount != 0) {
- /* end of non-repeating bytes */
- *rleptr++ = 0xfe;
- }
- if (j > 0) { /* if more data to do */
- /* set ptr back to start
- of repeat bytes */
- ptr--;
- }
- if (rleptr - rleptrstart > BufSize) {
- /* abort: too many rle bytes */
- break;
- }
- } while (j > 0); /* while more bytes to rle */
-
- /* if didnt abort && no non-repeating data */
- if (j < 1 && rlecount == 0) {
- /* check for trailing white space */
- /* line ends in trailing 0 */
- if (*(rleptr - 1) == 0x00) {
- /* ptr back to repeat count */
- rleptr -= 2;
- }
- }
- /* if line is just the cmd bytes */
- /* line null */
- if (rleptr - rleptrmark == RLENUMSTARTCMD) {
- /* reset ptr to start */
- rleptr = rleptrmark;
- }
- else {
- *rleptr++ = 0xff; /* end of rle line */
- }
- }
- i = rleptr - rleptrstart; /* calc size of rlebuf */
- /* if rle data is more send non-rle data */
- if (i > BufSize) {
- ptrstart = &PD->pd_PrintBuf[dataoffset -
- NUMSTARTCMD];
- ptr = ptrstart + BufSize - NUMLFCMD;
- /* if standard print mode and any black
- in this micro-line */
- if (stdmode && *(ptrstart + 2) < '4') {
- *ptr++ = 27;
- *ptr++ = 'k';
- *ptr++ = '0'; /* cr */
- *ptr++ = 27;
- *ptr++ = 'w';
- *ptr++ = 'B'; /* repeat black */
- }
- *ptr++ = 27;
- *ptr++ = 'k';
- *ptr++ = '1'; /* cr/lf */
- err = (*(PD->pd_PWrite))
- (ptrstart, ptr - ptrstart);
- }
- else { /* send rle data */
- /* if any black in this micro-line */
- if (rleptr - rleptrstart > 0 &&
- *(rleptrstart + 2) < '4') {
- *rleptr++ = 27;
- *rleptr++ = 'k';
- *rleptr++ = '0'; /* cr */
- *rleptr++ = 27;
- *rleptr++ = 'w';
- *rleptr++ = 'B'; /* repeat black */
- }
- *rleptr++ = 27;
- *rleptr++ = 'k';
- *rleptr++ = '1'; /* cr/lf */
- i = rleptr - rleptrstart; /* size of rlebuf */
- err = (*(PD->pd_PWrite))(rleptrstart, i);
- }
- if (err == PDERR_NOERR) {
- dataoffset = (dataoffset == NUMSTARTCMD ?
- BufSize : 0) + NUMSTARTCMD;
- rledataoffset = (rledataoffset ==
- RLENUMSTARTCMD ? RLEBufSize : 0) +
- RLENUMSTARTCMD;
- }
- break;
-
- case 3 : /* Clear and Init Buffer */
- /*
- ct - 0.
- x - 0.
- y - 0.
- */
- ptr = &PD->pd_PrintBuf[dataoffset];
- i = BufSize - NUMTOTALCMD - NUMLFCMD;
- do {
- *ptr++ = 0;
- } while (--i);
- for (ct=0; ct<NumColorBufs; ct++) {
- ptr = &PD->pd_PrintBuf[dataoffset -
- NUMSTARTCMD + ct * ColorSize];
- *ptr++ = 27;
- *ptr++ = 'g';
- *ptr++ = ct + '0'; /* color */
- *ptr++ = huns | '0';
- *ptr++ = tens | '0';
- *ptr++ = ones | '0'; /* printout width */
- *ptr = ','; /* terminator */
- }
- err = PDERR_NOERR; /* all ok */
- break;
-
- case 4 : /* Close Down */
- /*
- ct - error code.
- x - io_Special flag from IODRPReq.
- y - 0.
- */
- /* if user did not cancel print */
- if (ct != PDERR_CANCEL) {
- /* restore preferences pitch and margins */
- i = CalcMarg(PD->pd_Preferences.PrintLeftMargin
- , PD->pd_Preferences.PrintRightMargin);
- err = (*(PD->pd_PWrite))(MargBuf, i);
- }
- /* wait for both buffers to empty */
- (*(PD->pd_PBothReady))();
- if (PD->pd_PrintBuf != NULL) {
- FreeMem(PD->pd_PrintBuf, TotalBufSize);
- }
- err = PDERR_NOERR; /* all ok */
- break;
-
- case 5 : /* Pre-Master Initialization */
- /*
- ct - 0 or pointer to IODRPReq structure.
- x - io_Special flag from IODRPReq.
- y - 0.
- */
- StartBuf[PMODE - 1] = 'w';
- if ((x & SPECIAL_DENSITYMASK) < SPECIAL_DENSITY2) {
- /* standard graphics mode */
- StartBuf[PMODE] = 'e';
- stdmode = 1;
- }
- else {
- /* enhanced graphics mode */
- StartBuf[PMODE] = 'f';
- stdmode = 0;
- }
- PED->ped_MaxColumns = PD->pd_Preferences.PaperSize ==
- W_TRACTOR ? 90 : 80;
- /* def is 80 chars (8.0 in.),
- W_TRACTOR is 90 chars (9.0 in.) */
- PED->ped_MaxXDots = (PED->ped_XDotsInch *
- PED->ped_MaxColumns) / 10;
- /*
- The manual says that the printer has 1088 dots BUT I
- could never get more than 1080 out of it. This kludge
- is here as '121 * 90 / 10 = 1089' which is > 1080.
- */
- if (PED->ped_MaxXDots > 1080) {
- PED->ped_MaxXDots = 1080;
- }
- err = PDERR_NOERR; /* all ok */
- break;
- }
- return(err);
- }
-