home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 1.2 / amidev_cd_12.iso / reference_library / devices / dev_examples / epsonx_render.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-20  |  14.3 KB  |  331 lines

  1. /*
  2.         EpsonX (EX/FX/JX/LX/MX/RX) driver.
  3. */
  4.  
  5. #include <exec/types.h>
  6. #include <exec/nodes.h>
  7. #include <exec/lists.h>
  8. #include <exec/memory.h>
  9. #include "devices/printer.h"
  10. #include "devices/prtbase.h"
  11.  
  12. #define NUMSTARTCMD     7       /* # of cmd bytes before binary data */
  13. #define NUMENDCMD       1       /* # of cmd bytes after binary data */
  14. #define NUMTOTALCMD     (NUMSTARTCMD + NUMENDCMD)       /* total of above */
  15. #define NUMLFCMD        4       /* # of cmd bytes for linefeed */
  16. #define MAXCOLORBUFS    4       /* max # of color buffers */
  17.  
  18. #define STARTLEN        19
  19. #define PITCH           1
  20. #define CONDENSED       2
  21. #define LMARG           8
  22. #define RMARG           11
  23. #define DIREC           15
  24.  
  25. static ULONG TwoBufSize;
  26. static UWORD RowSize, ColorSize, NumColorBufs, dpi_code, spacing;
  27. static UWORD colorcodes[MAXCOLORBUFS];
  28.  
  29. Render(ct, x, y, status)
  30. long ct, x, y, status;
  31. {
  32.         extern void *AllocMem(), FreeMem();
  33.  
  34.         extern struct PrinterData *PD;
  35.         extern struct PrinterExtendedData *PED;
  36.  
  37.         UBYTE *CompactBuf();
  38.         static ULONG BufSize, TotalBufSize, dataoffset;
  39.         static UWORD spacing, colors[MAXCOLORBUFS];
  40.         /*
  41.                 00-01   \003P           set pitch (10 or 12 cpi)
  42.                 02-02   \022            set condensed fine (on or off)
  43.                 03-05   \033W\000       enlarge off
  44.                 06-08   \033ln          set left margin to n
  45.                 09-11   \033Qn          set right margin to n
  46.                 12-12   \015            carriage return
  47.                 13-15   \033U1          set uni-directional mode
  48.                 16-18   \033t\000       see kludge note below
  49.                 Kludge to get this to work on a CBM_MPS-1250  which interprets
  50.                 'ESCr' as go into reverse print mode.  The 'ESCt' tells it to
  51.                 get out of reverse print mode.  The 'NULL' is ignored by the
  52.                 CBM_MPS-1250 and required by all Epson printers as the
  53.                 terminator for the 'ESCtNULL' command which means select
  54.                 normal char set (which has no effect).
  55.         */
  56.  
  57.         static UBYTE StartBuf[STARTLEN+1] =
  58.                 "\033P\022\033W\000\033ln\033Qn\015\033U1\033t\000";
  59.  
  60.         UBYTE *ptr, *ptrstart;
  61.         int err;
  62.  
  63.         switch(status) {
  64.                 case 0 : /* Master Initialization */
  65.                         /*
  66.                                 ct      - pointer to IODRPReq structure.
  67.                                 x       - width of printed picture in pixels.
  68.                                 y       - height of printed picture in pixels.
  69.                         */
  70.                         RowSize = x;
  71.                         ColorSize = RowSize + NUMTOTALCMD;
  72.                         if (PD->pd_Preferences.PrintShade == SHADE_COLOR) {
  73.                                 NumColorBufs = MAXCOLORBUFS;
  74.                                 colors[0] = ColorSize * 3; /* Black */
  75.                                 colors[1] = ColorSize * 0; /* Yellow */
  76.                                 colors[2] = ColorSize * 1; /* Magenta */
  77.                                 colors[3] = ColorSize * 2; /* Cyan */
  78.                                 colorcodes[0] = 4; /* Yellow */
  79.                                 colorcodes[1] = 1; /* Magenta */
  80.                                 colorcodes[2] = 2; /* Cyan */
  81.                                 colorcodes[3] = 0; /* Black */
  82.                         }
  83.                         else { /* grey-scale or black&white */
  84.                                 NumColorBufs = 1;
  85.                                 colors[0] = ColorSize * 0; /* Black */
  86.                                 colorcodes[0] = 0; /* Black */
  87.                         }
  88.                         BufSize = ColorSize * NumColorBufs + NUMLFCMD;
  89.                         if (PED->ped_YDotsInch == 216) {
  90.                                 TwoBufSize = BufSize * 3;
  91.                                 TotalBufSize = BufSize * 6;
  92.                         }
  93.                         else if (PED->ped_YDotsInch == 144) {
  94.                                 TwoBufSize = BufSize * 2;
  95.                                 TotalBufSize = BufSize * 4;
  96.                         }
  97.                         else {
  98.                                 TwoBufSize = BufSize * 1;
  99.                                 TotalBufSize = BufSize * 2;
  100.                         }
  101.                         PD->pd_PrintBuf = AllocMem(TotalBufSize, MEMF_PUBLIC);
  102.                         if (PD->pd_PrintBuf == NULL) {
  103.                                 err = PDERR_BUFFERMEMORY;
  104.                         }
  105.                         else {
  106.                                 dataoffset = NUMSTARTCMD;
  107.                                 /*
  108.                                         This printer prints graphics within its
  109.                                         text margins.  This code makes sure the
  110.                                         printer is in 10 cpi and then sets the
  111.                                         left and right margins to their minimum
  112.                                         and maximum values (respectively).  A
  113.                                         carriage return is sent so that the
  114.                                         print head is at the leftmost position
  115.                                         as this printer starts printing from
  116.                                         the print head's position.  The printer
  117.                                         is put into unidirectional mode to
  118.                                         reduce wavy vertical lines.
  119.                                 */
  120.                                 StartBuf[PITCH] = 'P'; /* 10 cpi */
  121.                                 StartBuf[CONDENSED] = '\022'; /* off */
  122.                                 /* left margin of 1 */
  123.                                 StartBuf[LMARG] = 0;
  124.                                 /* right margin of 80 or 136 */
  125.                                 StartBuf[RMARG] = PD->pd_Preferences.
  126.                                         PaperSize == W_TRACTOR ? 136 : 80;
  127.                                 /* uni-directional mode */
  128.                                 StartBuf[DIREC] = '1';
  129.                                 err = (*(PD->pd_PWrite))(StartBuf, STARTLEN);
  130.                         }
  131.                         break;
  132.  
  133.                 case 1 : /* Scale, Dither and Render */
  134.                         /*
  135.                                 ct      - pointer to PrtInfo structure.
  136.                                 x       - 0.
  137.                                 y       - row # (0 to Height - 1).
  138.                         */
  139.                         Transfer(ct, y, &PD->pd_PrintBuf[dataoffset], colors,
  140.                                 BufSize);
  141.                         err = PDERR_NOERR; /* all ok */
  142.                         break;
  143.  
  144.                 case 2 : /* Dump Buffer to Printer */
  145.                         /*
  146.                                 ct      - 0.
  147.                                 x       - 0.
  148.                                 y       - # of rows sent (1 to NumRows).
  149.  
  150.                         */
  151.                         /* white-space strip */
  152.                         ptrstart = &PD->pd_PrintBuf[dataoffset - NUMSTARTCMD];
  153.                         if (PED->ped_YDotsInch == 72) {
  154.                                 /* y range : 1 to 8 */
  155.                                 y = y * 3 - spacing;
  156.                                 ptr = CompactBuf(ptrstart + NUMSTARTCMD,
  157.                                         ptrstart, y, 1);
  158.                         }
  159.                         else if (PED->ped_YDotsInch == 144) {
  160.                                 /* y range : 1 to 16 */
  161.                                 ptr = CompactBuf(ptrstart + NUMSTARTCMD,
  162.                                         ptrstart, 2, 1);
  163.                                 if (y > 1) {
  164.                                         ptr = CompactBuf(&PD->pd_PrintBuf[
  165.                                                 dataoffset + BufSize],
  166.                                                 ptr, y * 3 / 2 - 2, 0);
  167.                                 }
  168.                         }
  169.                         else if (PED->ped_YDotsInch == 216) {
  170.                                 /* y range : 1 to 24 */
  171.                                 ptr = CompactBuf(ptrstart + NUMSTARTCMD,
  172.                                         ptrstart, 1, 1);
  173.                                 if (y > 1) {
  174.                                         ptr = CompactBuf(&PD->pd_PrintBuf[
  175.                                                 dataoffset + BufSize],
  176.                                                 ptr, 1, 0);
  177.                                 }
  178.                                 if (y > 2) {
  179.                                         ptr = CompactBuf(&PD->pd_PrintBuf[
  180.                                                 dataoffset + BufSize * 2],
  181.                                                 ptr, y - 2, 0);
  182.                                 }
  183.                         }
  184.                         err = (*(PD->pd_PWrite))(ptrstart, ptr - ptrstart);
  185.                         if (err == PDERR_NOERR) {
  186.                                 dataoffset = (dataoffset == NUMSTARTCMD ?
  187.                                         TwoBufSize : 0) + NUMSTARTCMD;
  188.                         }
  189.                         break;
  190.  
  191.                 case 3 : /* Clear and Init Buffer */
  192.                         /*
  193.                                 ct      - 0.
  194.                                 x       - 0.
  195.                                 y       - 0.
  196.                         */
  197.                         ClearAndInit(&PD->pd_PrintBuf[dataoffset]);
  198.                         err = PDERR_NOERR;
  199.                         break;
  200.  
  201.                 case 4 : /* Close Down */
  202.                         /*
  203.                                 ct      - error code.
  204.                                 x       - io_Special flag from IODRPReq.
  205.                                 y       - 0.
  206.                         */
  207.                         err = PDERR_NOERR; /* assume all ok */
  208.                         /* if user did not cancel print */
  209.                         if (ct != PDERR_CANCEL) {
  210.                                 /* restore preferences pitch and margins */
  211.                                 if (PD->pd_Preferences.PrintPitch == ELITE) {
  212.                                         StartBuf[PITCH] = 'M'; /* 12 cpi */
  213.                                 }
  214.                                 else if (PD->pd_Preferences.PrintPitch == FINE) {
  215.                                         StartBuf[CONDENSED] = '\017'; /* on */
  216.                                 }
  217.                                 StartBuf[LMARG] =
  218.                                         PD->pd_Preferences.PrintLeftMargin - 1;
  219.                                 StartBuf[RMARG] =
  220.                                         PD->pd_Preferences.PrintRightMargin;
  221.                                 StartBuf[DIREC] = '0'; /* bi-directional */
  222.                                 err = (*(PD->pd_PWrite))(StartBuf, STARTLEN);
  223.                         }
  224.                         (*(PD->pd_PBothReady))();
  225.                         if (PD->pd_PrintBuf != NULL) {
  226.                                 FreeMem(PD->pd_PrintBuf, TotalBufSize);
  227.                         }
  228.                         break;
  229.  
  230.                 case 5 :  /* Pre-Master Initialization */
  231.                         /*
  232.                                 ct      - 0 or pointer to IODRPReq structure.
  233.                                 x       - io_Special flag from IODRPReq.
  234.                                 y       - 0.
  235.                         */
  236.                         /* kludge for sloppy tractor mechanism */
  237.                         spacing = PD->pd_Preferences.PaperType == SINGLE ?
  238.                                 1 : 0;
  239.                         dpi_code = SetDensity(x & SPECIAL_DENSITYMASK);
  240.                         err = PDERR_NOERR;
  241.                         break;
  242.         }
  243.         return(err);
  244. }
  245.  
  246. UBYTE *CompactBuf(ptrstart, ptr2start, y, flag)
  247. UBYTE *ptrstart, *ptr2start;
  248. long y;
  249. int flag; /* 0 - not first pass, !0 - first pass */
  250. {
  251.         static int x;
  252.         UBYTE *ptr, *ptr2;
  253.         long ct;
  254.         int i;
  255.  
  256.         ptr2 = ptr2start; /* where to put the compacted data */
  257.         if (flag) {
  258.                 x = 0; /* flag no transfer required yet */
  259.         }
  260.  
  261.         for (ct=0; ct<NumColorBufs; ct++, ptrstart += ColorSize) {
  262.                 i = RowSize;
  263.                 ptr = ptrstart + i - 1;
  264.                 while (i > 0 && *ptr == 0) {
  265.                         i--;
  266.                         ptr--;
  267.                 }
  268.  
  269.                 if (i != 0) { /* if data */
  270.                         *(++ptr) = 13;                  /* <cr> */
  271.                         ptr = ptrstart - NUMSTARTCMD;
  272.                         *ptr++ = 27;
  273.                         *ptr++ = 'r';
  274.                         *ptr++ = colorcodes[ct];        /* color */
  275.                         *ptr++ = 27;
  276.                         *ptr++ = dpi_code;              /* density */
  277.                         *ptr++ = i & 0xff;
  278.                         *ptr++ = i >> 8;                /* size */
  279.                         i += NUMTOTALCMD;
  280.                         if (x != 0) { /* if must transfer data */
  281.                                 /* get src start */
  282.                                 ptr = ptrstart - NUMSTARTCMD;
  283.                                 do { /* transfer and update dest ptr */
  284.                                         *ptr2++ = *ptr++;
  285.                                 } while (--i);
  286.                         }
  287.  
  288.                         else { /* no transfer required */
  289.                                 ptr2 += i; /* update dest ptr */
  290.                         }
  291.                 }
  292.  
  293.                 if (i != RowSize + NUMTOTALCMD) { /* if compacted or 0 */
  294.                         x = 1; /* flag that we need to transfer next time */
  295.                 }
  296.         }
  297.  
  298.         *ptr2++ = 13; /* cr */
  299.         *ptr2++ = 27;
  300.         *ptr2++ = 'J';
  301.         *ptr2++ = y; /* y/216 lf */
  302.         return(ptr2);
  303. }
  304.  
  305. ClearAndInit(ptr)
  306. UBYTE *ptr;
  307. {
  308.         ULONG *lptr, i, j;
  309.  
  310.         /*
  311.                 Note : Since 'NUMTOTALCMD + NUMLFCMD' is > 3 bytes if is safe
  312.                 to do the following to speed things up.
  313.         */
  314.         i = TwoBufSize - NUMTOTALCMD - NUMLFCMD;
  315.         j = (ULONG)ptr;
  316.         if (!(j & 1)) { /* if on a word boundary, clear by longs */
  317.                 i = (i + 3) / 4;
  318.                 lptr = (ULONG *)ptr;
  319.                 do {
  320.                         *lptr++ = 0;
  321.                 } while (--i);
  322.         }
  323.         else { /* clear by bytes */
  324.                 do {
  325.                         *ptr++ = 0;
  326.                 } while (--i);
  327.         }
  328.         return(0);
  329. }
  330.  
  331.