home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 377b.lha / devices / printer / xerox / render.c < prev    next >
Encoding:
C/C++ Source or Header  |  1980-02-03  |  10.7 KB  |  371 lines

  1. /* Copyright (c) 1990 Commodore-Amiga, Inc.
  2.  *
  3.  * This example is provided in electronic form by Commodore-Amiga, Inc. for
  4.  * use with the 1.3 revisions of the Addison-Wesley Amiga reference manuals. 
  5.  * The 1.3 Addison-Wesley Amiga Reference Manual series contains additional
  6.  * information on the correct usage of the techniques and operating system
  7.  * functions presented in this example.  The source and executable code of
  8.  * this example may only be distributed in free electronic form, via bulletin
  9.  * board or as part of a fully non-commercial and freely redistributable
  10.  * diskette.  Both the source and executable code (including comments) must
  11.  * be included, without modification, in any copy.  This example may not be
  12.  * published in printed form or distributed with any commercial product.
  13.  * However, the programming techniques and support routines set forth in
  14.  * this example may be used in the development of original executable
  15.  * software products for Commodore Amiga computers.
  16.  * All other rights reserved.
  17.  * This example is provided "as-is" and is subject to change; no warranties
  18.  * are made.  All use is at your own risk.  No liability or responsibility
  19.  * is assumed.
  20.  */
  21.  
  22. #include <exec/types.h>
  23. #include <exec/nodes.h>
  24. #include <exec/lists.h>
  25. #include <exec/memory.h>
  26. #include <devices/printer.h>
  27. #include <devices/prtbase.h>
  28.  
  29. #define NUMSTARTCMD    7    /* # of cmd bytes before binary data */
  30. #define NUMENDCMD    0    /* # of cmd bytes after binary data */
  31. #define NUMTOTALCMD     (NUMSTARTCMD + NUMENDCMD)    /* total of above */
  32. #define NUMLFCMD    9    /* # of cmd bytes for linefeed */
  33. #define MAXCOLORBUFS    16    /* max # of color buffers */
  34.  
  35. #define RLEMAX        136
  36. #define RLENUMSTARTCMD    3    /* # of cmd bytes before binary data */
  37. #define RLENUMENDCMD    1    /* # of cmd bytes after binary data */
  38. #define RLENUMTOTALCMD     (RLENUMSTARTCMD + RLENUMENDCMD)    /* total of above */
  39. #define RLESAFETY    10    /* extra room for overwrites */
  40.  
  41. #define PMODE        15    /* index into StartBuf for print mode */
  42. #define STARTLEN    16    /* length of start buffer */
  43.  
  44. extern UBYTE MargBuf[];
  45.  
  46. Render(ct, x, y, status)
  47. long ct, x, y, status;
  48. {
  49.     extern void *AllocMem(), FreeMem();
  50.     extern struct PrinterData *PD;
  51.     extern struct PrinterExtendedData *PED;
  52.  
  53.     static UWORD RowSize, ColorSize, BufSize, TotalBufSize, dataoffset;
  54.     static UWORD colors[MAXCOLORBUFS]; /* color indexes */
  55.     static UWORD color_order[] =
  56.         {0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7, 12, 13, 14, 15};
  57.     static UWORD huns, tens, ones; /* used to program buffer size */
  58.     static UWORD NumColorBufs; /* actually # of color buffers */
  59.     /*
  60.         00-02    \033F0        set 10 cpi
  61.         03-07    \033l05\r    set left margin to .5 inches
  62.         09-12    \033r95\r    set right margin to 9.5 inches
  63.         13-15    \033we        select standard (e) or
  64.                     enhanced (f) graphics mode.
  65.     */
  66.     static UBYTE stdmode, StartBuf[STARTLEN] =
  67. {0x1b,'F','0',0x1b,'l','0','5',0x0d,0x1b,'r','9','5',0x0d,0x1b,'w','e'};
  68.  
  69.     UBYTE *ptr, *ptrstart;
  70.     int i, err;
  71.  
  72.     static UWORD RLEBufSize, rledataoffset;
  73.     static UBYTE *RLEBuf;
  74.     UBYTE *rleptrstart, *rleptr, *rleptrmark, rledata;
  75.     int rlecount, j;
  76.  
  77.     switch(status) {
  78.         case 0 : /* Master Initialization */
  79.             /*
  80.                 ct    - pointer to IODRPReq structure.
  81.                 x    - width of printed picture in pixels.
  82.                 y    - height of printed picture in pixels.
  83.             */
  84.             /* calc # of bytes of row data */
  85.             RowSize = (x + 7) / 8;
  86.             /* size of each color buf */
  87.             ColorSize = RowSize + NUMTOTALCMD;
  88.             huns = RowSize / 100;
  89.             tens = (RowSize - huns * 100) / 10;
  90.             ones = RowSize % 10;
  91.             if (PD->pd_Preferences.PrintShade == SHADE_COLOR) {
  92.                 NumColorBufs = MAXCOLORBUFS;
  93.             }
  94.             else {
  95.                 NumColorBufs = 4;
  96.             }
  97.             BufSize = ColorSize * NumColorBufs + NUMLFCMD;
  98.             TotalBufSize = BufSize * 2;
  99.             RLEBufSize = BufSize + RLESAFETY;
  100.             TotalBufSize += RLEBufSize * 2;
  101.             /*
  102.                 My color order:        B, Y, M, C
  103.                 Xerox's color order:    B, M, Y, C
  104.             */
  105.             for (i=0; i<NumColorBufs; i++) {
  106.                 colors[color_order[i]] = ColorSize * i;
  107.             }
  108.             PD->pd_PrintBuf = AllocMem(TotalBufSize, MEMF_PUBLIC);
  109.             if (PD->pd_PrintBuf == NULL) {
  110.                 err = PDERR_BUFFERMEMORY; /* no mem */
  111.             }
  112.             else {
  113.                 dataoffset = NUMSTARTCMD;
  114.                 err = (*(PD->pd_PWrite))(StartBuf, STARTLEN);
  115.                 RLEBuf = &PD->pd_PrintBuf[BufSize * 2];
  116.                 rledataoffset = RLENUMSTARTCMD;
  117.             }
  118.             break;
  119.  
  120.         case 1 : /* Scale, Dither and Render */
  121.             /*
  122.                 ct    - pointer to PrtInfo structure.
  123.                 x    - 0.
  124.                 y    - row # (0 to Height - 1).
  125.             */
  126.             Transfer(ct, y, &PD->pd_PrintBuf[dataoffset], colors);
  127.             err = PDERR_NOERR; /* all ok */
  128.             break;
  129.  
  130.         case 2 : /* Dump Buffer to Printer */
  131.             /*
  132.                 ct    - 0.
  133.                 x    - 0.
  134.                 y    - # of rows sent (1 to NumRows).
  135.             */
  136.             /* Run-Length Encode (rle) the data */
  137.             rleptrstart = rleptr =
  138.                 &RLEBuf[rledataoffset - RLENUMSTARTCMD];
  139.             /* ptr to data */
  140.             ptrstart = &PD->pd_PrintBuf[dataoffset];
  141.             for (ct=0; ct<NumColorBufs;
  142.                 ct++, ptrstart += ColorSize) {
  143.                 /* save start posn for this color */
  144.                 rleptrmark = rleptr;
  145.                 *rleptr++ = 27; /* rle start cmd */
  146.                 *rleptr++ = 'h';
  147.                 *rleptr++ = ct | '0'; /* color code */
  148.                 ptr = ptrstart; /* get ptr to bytes to rle */
  149.                 j = RowSize - 1; /* # of bytes left to rle */
  150.                 do {
  151.                     /* first do repeating bytes */
  152.                     /* get goal (repeating) byte */
  153.                     rledata = *ptr++;
  154.                     /* this many repetitions left to go*/
  155.                     i = RLEMAX - 1;
  156.                     /* while repeating and not too many
  157.                         and more to do */
  158.                     while (*ptr == rledata && i > 0 &&
  159.                         j > 0) {
  160.                         i--; /* one more rle byte */
  161.                         /* advance ptr to next byte */
  162.                         ptr++;
  163.                         /* one less byte to look at */
  164.                         j--;
  165.                     }
  166.                     /* calc repeating byte count */
  167.                     if ((rlecount = RLEMAX - i) == 1) {
  168.                         /* if only 1 then no repeat */
  169.                         rlecount = 0;
  170.                     }
  171.                     else {
  172.                         /* dont forget the goal byte */
  173.                         j--;
  174.                     }
  175.                     /* if there was repeat data */
  176.                     if (rlecount != 0) {
  177.                         /* save repeat count */
  178.                         *rleptr++ = rlecount;
  179.                         /* save repeat byte */
  180.                         *rleptr++ = rledata;
  181.                         /* get non-repeat goal byte */
  182.                         rledata = *ptr++;
  183.                     }
  184.                     /* now do non-repeating data */
  185.                     /* no non-repeating bytes yet */
  186.                     rlecount = 0;
  187.                     if (*ptr != rledata && j >= 0) {
  188.                         /* non-repeat data follows */
  189.                         *rleptr++ = 0x00;
  190.                     }
  191.                     /* while non-repeating and more to do */
  192.                     while (*ptr != rledata && j >= 0) {
  193.                         /* save byte */
  194.                         *rleptr++ = rledata;
  195.                         /* if byte same as terminator */
  196.                         if (rledata == 0xfe) {
  197.                             /* save byte (again) */
  198.                             *rleptr++ = rledata;
  199.                         }
  200.                         /* one more non-repeat byte */
  201.                         rlecount++;
  202.                         /* get goal byte */
  203.                         rledata = *ptr++;
  204.                         /* one less byte to look at */
  205.                         j--;
  206.                     }
  207.                     if (rlecount != 0) {
  208.                         /* end of non-repeating bytes */
  209.                         *rleptr++ = 0xfe;
  210.                     }
  211.                     if (j > 0) { /* if more data to do */
  212.                         /* set ptr back to start
  213.                             of repeat bytes */
  214.                         ptr--;
  215.                     }
  216.                     if (rleptr - rleptrstart > BufSize) {
  217.                         /* abort: too many rle bytes */
  218.                         break;
  219.                     }
  220.                 } while (j > 0); /* while more bytes to rle */
  221.  
  222.                 /* if didnt abort && no non-repeating data */
  223.                 if (j < 1 && rlecount == 0) {
  224.                     /* check for trailing white space */
  225.                     /* line ends in trailing 0 */
  226.                     if (*(rleptr - 1) == 0x00) {
  227.                         /* ptr back to repeat count */
  228.                         rleptr -= 2;
  229.                     }
  230.                 }
  231.                 /* if line is just the cmd bytes */
  232.                 /* line null */
  233.                 if (rleptr - rleptrmark == RLENUMSTARTCMD) {
  234.                     /* reset ptr to start */
  235.                     rleptr = rleptrmark;
  236.                 }
  237.                 else {
  238.                     *rleptr++ = 0xff; /* end of rle line */
  239.                 }
  240.             }
  241.             i = rleptr - rleptrstart; /* calc size of rlebuf */
  242.             /* if rle data is more send non-rle data */
  243.             if (i > BufSize) {
  244.                 ptrstart = &PD->pd_PrintBuf[dataoffset -
  245.                     NUMSTARTCMD];
  246.                 ptr = ptrstart + BufSize - NUMLFCMD;
  247.                 /* if standard print mode and any black
  248.                     in this micro-line */
  249.                 if (stdmode && *(ptrstart + 2) < '4') {
  250.                     *ptr++ = 27;
  251.                     *ptr++ = 'k';
  252.                     *ptr++ = '0';    /* cr */
  253.                     *ptr++ = 27;
  254.                     *ptr++ = 'w';
  255.                     *ptr++ = 'B';    /* repeat black */
  256.                 }
  257.                 *ptr++ = 27;
  258.                 *ptr++ = 'k';
  259.                 *ptr++ = '1';        /* cr/lf */
  260.                 err = (*(PD->pd_PWrite))
  261.                     (ptrstart, ptr - ptrstart);
  262.             }
  263.             else { /* send rle data */
  264.                 /* if any black in this micro-line */
  265.                 if (rleptr - rleptrstart > 0 &&
  266.                     *(rleptrstart + 2) < '4') {
  267.                     *rleptr++ = 27;
  268.                     *rleptr++ = 'k';
  269.                     *rleptr++ = '0'; /* cr */
  270.                     *rleptr++ = 27;
  271.                     *rleptr++ = 'w';
  272.                     *rleptr++ = 'B'; /* repeat black */
  273.                 }
  274.                 *rleptr++ = 27;
  275.                 *rleptr++ = 'k';
  276.                 *rleptr++ = '1';    /* cr/lf */
  277.                 i = rleptr - rleptrstart; /* size of rlebuf */
  278.                 err = (*(PD->pd_PWrite))(rleptrstart, i);
  279.             }
  280.             if (err == PDERR_NOERR) {
  281.                 dataoffset = (dataoffset == NUMSTARTCMD ?
  282.                     BufSize : 0) + NUMSTARTCMD;
  283.                 rledataoffset = (rledataoffset ==
  284.                     RLENUMSTARTCMD ? RLEBufSize : 0) +
  285.                     RLENUMSTARTCMD;
  286.             }
  287.             break;
  288.  
  289.         case 3 : /* Clear and Init Buffer */
  290.             /*
  291.                 ct    - 0.
  292.                 x    - 0.
  293.                 y    - 0.
  294.             */
  295.             ptr = &PD->pd_PrintBuf[dataoffset];
  296.             i = BufSize - NUMTOTALCMD - NUMLFCMD;
  297.             do {
  298.                 *ptr++ = 0;
  299.             } while (--i);
  300.             for (ct=0; ct<NumColorBufs; ct++) {
  301.                 ptr = &PD->pd_PrintBuf[dataoffset -
  302.                     NUMSTARTCMD + ct * ColorSize];
  303.                 *ptr++ = 27;
  304.                 *ptr++ = 'g';
  305.                 *ptr++ = ct + '0';    /* color */
  306.                 *ptr++ = huns | '0';
  307.                 *ptr++ = tens | '0';
  308.                 *ptr++ = ones | '0';    /* printout width */
  309.                 *ptr = ',';        /* terminator */
  310.             }
  311.             err = PDERR_NOERR; /* all ok */
  312.             break;
  313.  
  314.         case 4 : /* Close Down */
  315.             /*
  316.                 ct    - error code.
  317.                 x    - io_Special flag from IODRPReq.
  318.                 y    - 0.
  319.             */
  320.             /* if user did not cancel print */
  321.             if (ct != PDERR_CANCEL) {
  322.                 /* restore preferences pitch and margins */
  323.                 i = CalcMarg(PD->pd_Preferences.PrintLeftMargin
  324.                     , PD->pd_Preferences.PrintRightMargin);
  325.                 err = (*(PD->pd_PWrite))(MargBuf, i);
  326.             }
  327.             /* wait for both buffers to empty */
  328.             (*(PD->pd_PBothReady))();
  329.             if (PD->pd_PrintBuf != NULL) {
  330.                 FreeMem(PD->pd_PrintBuf, TotalBufSize);
  331.             }
  332.             err = PDERR_NOERR; /* all ok */
  333.             break;
  334.  
  335.         case 5 : /* Pre-Master Initialization */
  336.             /*
  337.                 ct    - 0 or pointer to IODRPReq structure.
  338.                 x    - io_Special flag from IODRPReq.
  339.                 y    - 0.
  340.             */
  341.             StartBuf[PMODE - 1] = 'w';
  342.             if ((x & SPECIAL_DENSITYMASK) < SPECIAL_DENSITY2) {
  343.                 /* standard graphics mode */
  344.                 StartBuf[PMODE] = 'e';
  345.                 stdmode = 1;
  346.             }
  347.             else {
  348.                 /* enhanced graphics mode */
  349.                 StartBuf[PMODE] = 'f';
  350.                 stdmode = 0;
  351.             }
  352.             PED->ped_MaxColumns = PD->pd_Preferences.PaperSize ==
  353.                 W_TRACTOR ? 90 : 80;
  354.             /* def is 80 chars (8.0 in.),
  355.                 W_TRACTOR is 90 chars (9.0 in.) */
  356.             PED->ped_MaxXDots = (PED->ped_XDotsInch *
  357.                 PED->ped_MaxColumns) / 10;
  358.             /*
  359.             The manual says that the printer has 1088 dots BUT I
  360.             could never get more than 1080 out of it.  This kludge
  361.             is here as '121 * 90 / 10 = 1089' which is > 1080.
  362.             */
  363.             if (PED->ped_MaxXDots > 1080) {
  364.                  PED->ped_MaxXDots = 1080;
  365.             }
  366.             err = PDERR_NOERR; /* all ok */
  367.             break;
  368.     }
  369.     return(err);
  370. }
  371.