/*
 *        Render function
 *
 *        HP_DeskJet_670C driver with color gfx
 */

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <proto/exec.h>
#include <devices/prtbase.h>
#include <devices/printer.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 LENGTH          8
#define PLANES         27
#define WIDTH          33
#define NUMCOLORCMD     7       /* Cmds for each color buffer */
#define MAXCOLORBUFS    4
#define STARTCMDSIZE   48

/* Prototypes */

int Render(long ct, long x, long y, long status);
int DumpBWPrint(UBYTE *colors[],UWORD BufSize);
int DumpColorPrint(UBYTE *colors[],UWORD BufSize);
extern void SetDensity(ULONG code);
extern int Transfer(struct PrtInfo *PInfo, UWORD y, UBYTE *colors[], UWORD RowSize, UWORD NumColorBufs);
STATIC VOID CorrectColours(UBYTE * gamma_table, UBYTE *colors[], UWORD width);
extern LONG StripWhiteSpace(BYTE *source, LONG size);
extern LONG CompressMethod2(UBYTE *src, UBYTE *dest, LONG count);

/*
        00-04   \033&l0L        perf skip mode off
        05-11   \033&l000F      page length
        12-18   \033*t075R      set raster graphics resolution (dpi)
        19-23   \033*b0M        add compression (Method 0)
        24-29   \033*r01U       Num of raster planes per row (PLANES)
        30-37   \033*r1440S     set raster gfx width (WIDTH)
        38-42   \033*o3D        Set Gfx depletion (mid value)
        43-47   \033*r0A        start raster graphics
*/
char StartCmd[STARTCMDSIZE + 1] = "\033&l0L\033&l000F\033*t075R\033*b0M\033*r01U\033*r1440S\033*o3D\033*r0A";
static UWORD RowSize, NumColorBufs;
STATIC UBYTE * gamma_table;

/* Render graphics to printer */

Render(ct, x, y, status)
long ct, x, y, status;
{
        extern void *AllocMem(), FreeMem();

        extern struct PrinterData *PD;
        extern struct PrinterExtendedData *PED;
        extern UBYTE GammaTables[15][256];

        static UWORD BufSize, textlength;
        static UBYTE *colors[MAXCOLORBUFS];
        UBYTE *ptr;
        int i, err, papersize, lpi, len;
        long row;

        err=PDERR_NOERR;
        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.
                        */
                        RowSize = (x + 7) / 8;
                        if (PD->pd_Preferences.PrintShade == SHADE_COLOR) {
                           NumColorBufs = MAXCOLORBUFS;
                           StartCmd[PLANES] = '-';          /* 4 planes, KCMY */
                           StartCmd[PLANES+1] = '4';
                        }
                        else
                        {
                           NumColorBufs = 1;
                        }
                        BufSize = RowSize * 2; /* Double buffered */
                        
                        lpi = 6;
                        if (PD->pd_Preferences.PrintSpacing == EIGHT_LPI)
                           lpi = 8;
                         
        		papersize = PD->pd_Preferences.PaperSize;
	        	switch (papersize) 
		        {
		        case US_LETTER:
			        textlength = 10 * lpi;
                                break;
		        case US_LEGAL:
                                textlength = 13 * lpi;
                                break;
		        case EURO_A4:
			        textlength = (lpi == 8 ? 85 : 65);
                                break;
		        default:   /* Custom size */
	                        textlength = PD->pd_Preferences.PaperLength;	                              		        
		        }
                        /* Set page length */
                        StartCmd[LENGTH] = textlength / 100 | '0';
                        textlength = textlength - (textlength / 100) * 100;
                        StartCmd[LENGTH+1] = textlength / 10 | '0';
                        StartCmd[LENGTH+2] = textlength % 10 | '0';
 
                        row = x;                               /* Set Raster Width */
                        StartCmd[WIDTH] = row / 1000 | '0';
                        row = row % 1000;
                        StartCmd[WIDTH+1] = row / 100 | '0';
                        row = row % 100;
                        StartCmd[WIDTH+2] = row / 10 | '0';
                        StartCmd[WIDTH+3] = row % 10 | '0';

                        if (PD->pd_Preferences.PrintThreshold>0)
                           gamma_table = GammaTables[PD->pd_Preferences.PrintThreshold];
                        else
                           gamma_table = NULL;

                        for (i=0; i< NumColorBufs; i++) {
                            if (!(colors[i] = AllocMem(BufSize, MEMF_PUBLIC)))
                               err = PDERR_BUFFERMEMORY;
                        }
                                
                        if (err != PDERR_BUFFERMEMORY) {
                            /* perf skip mode off, set dpi, start raster gfx */
                            err = (*(PD->pd_PWrite))(StartCmd, STARTCMDSIZE-1);
                        }
                        break;

                case 1 : /* Scale, Dither and Render */
                        /*
                                ct      - pointer to PrtInfo structure.
                                x       - 0.
                                y       - row # (0 to Height - 1).
                        */
                        Transfer((struct PrtInfo *)ct, y, colors, RowSize, NumColorBufs);
                        err = PDERR_NOERR; /* all ok */
                        break;

                case 2 : /* Dump Buffer to Printer */
                        /*
                                ct      - 0.
                                x       - 0.
                                y       - # of rows sent (1 to NumRows).

                                White-space strip.
                        */

                       if (gamma_table != NULL && NumColorBufs == 4) 
                          CorrectColours(gamma_table, colors, BufSize); 

                       if (NumColorBufs == 4)  
                          err = DumpColorPrint(colors, BufSize);
                       else
                          err = DumpBWPrint(colors,BufSize);  
                        break;

                case 3 : /* Clear and Init Buffer */
                        /*
                                ct      - 0.
                                x       - 0.
                                y       - 0.
                        */
                        for (i=0; i<NumColorBufs; i++) {
                            ptr = colors[i];
                            len = BufSize;
                            do {                                
                                *ptr++ = 0;
                            } while (--len);
                        }
                       break;

                case 4 : /* Close Down */
                        /*
                                ct      - error code.
                                x       - io_Special flag from IODRPReq struct
                                y       - 0.
                        */
                        err = PDERR_NOERR; /* assume all ok */
                        /* if user did not cancel the print */
                        if (ct != PDERR_CANCEL) {
                                /* end raster graphics, perf skip mode on */
                                if ((err = (*(PD->pd_PWrite))
                                        ("\033*rC\033&l1L", 9)) == PDERR_NOERR) {
                                        /* if want to unload paper */
                                        if (!(x & SPECIAL_NOFORMFEED)) {
                                           err = (*(PD->pd_PWrite))("\014", 1);
                                        } 
                                }
                        }
                        /*
                                flag that there is no alpha data waiting that
                                needs a formfeed (since we just did one)
                        */
                        PED->ped_PrintMode = 0;
                         /* wait for both buffers to empty */
                        (*(PD->pd_PBothReady))();
                        for (i=0; i<NumColorBufs; i++) {
                           if (colors[i] != NULL) 
                                FreeMem(colors[i], BufSize);
                        }
                        break;

                case 5 : /* Pre-Master Initialization */
                        /*
                                ct      - 0 or pointer to IODRPReq structure.
                                x       - io_Special flag from IODRPReq struct
                                y       - 0.
                        */
                        /* select density */
                        SetDensity(x & SPECIAL_DENSITYMASK);
                        break;
        }
        return(err);
}

/* New dump routines which replaces older CompactBuf routine 8/4/02 */

int DumpBWPrint(UBYTE *colors[],UWORD BufSize)
{
    /* Dump B&W grpahic data */
    
    UWORD i=0, size;
    UBYTE *ptr;
    char cmd[10] = "\033*b0m000W";
    int err, method, mem;
    
    /* Remove trailing white space */
    mem = FALSE;
    size = StripWhiteSpace(colors[0], BufSize);
    if (size>0) {     
        /* Compress data */
        if (ptr = AllocMem(BufSize, MEMF_PUBLIC|MEMF_CLEAR)) {
            i = CompressMethod2(colors[0], ptr, size);
            mem = TRUE;
            if (i<0) {
                method = 0;
                i = size;
            } else
                method = 2;
        }   
        else {
            ptr = colors[0];
            method = 0;
            mem = FALSE;
        }
        
        cmd[3] = method | '0';
        cmd[5] = (i/100) | '0';
        cmd[6] = (i - (i/100)*100) / 10 | '0';
        cmd[7] = i % 10 | '0';
    } else {
        method = 0;
        cmd[3] = method | '0';
        cmd[5] = '0';
        cmd[6] = '0';
        cmd[7] = '0';
        ptr=colors[0];
    }
    
    (*(PD->pd_PWrite))(cmd,9);
    err = (*(PD->pd_PWrite))(ptr, i);
    if (mem) FreeMem(ptr, BufSize);
    return err;
}

int DumpColorPrint(UBYTE *colors[],UWORD BufSize)
{
    /* Dump Color graphic data */
    
    UWORD i=0, size;
    UBYTE *ptr;
    char startcmd[6] = "\033*b0W";
    char colorcmd[10] = "\033*b0m000V";
    int err, ct, method, mem;
     
    err = (*(PD->pd_PWrite))(startcmd,5);
    mem = FALSE;
    
    for (ct=0; ct<4 && err == PDERR_NOERR; ct++) {
        
        /* Strip trailing White Space */
        size = StripWhiteSpace(colors[ct], BufSize);
        if (size>0) {
            /* Compress data */
            if (ptr = AllocMem(BufSize, MEMF_PUBLIC|MEMF_CLEAR)) {
                 i = CompressMethod2(colors[ct], ptr, size);
                 mem = TRUE;
                 if (i < 0) {
                    method = 0;
                    i = size;
                 } else
                    method = 2; 
            }
            else {
                 ptr = colors[ct];
                 method = 0;
                 mem = FALSE;
            }
   
            colorcmd[3] = method | '0';
            colorcmd[5] = (i/100) | '0';
            colorcmd[6] = (i - (i/100)*100) / 10 | '0';
            colorcmd[7] = i % 10 | '0';
        } else {
            method = 0;
            colorcmd[3] = method | '0';
            colorcmd[5] = '0';
            colorcmd[6] = '0';
            colorcmd[7] = '0';
            ptr = colors[ct];
        }  
        (*(PD->pd_PWrite))(colorcmd,9);
        err = (*(PD->pd_PWrite))(ptr, i);
        if (mem) FreeMem(ptr, BufSize);
    }
   return err;
}

/* This routine makes a local copy of the colour data and applies
 * gamma correction to it.
 */
STATIC VOID CorrectColours(UBYTE *gamma_table, UBYTE *colors[], UWORD width)
{
	LONG x,c;
        UBYTE *ptrstart;
        
        for (c=0; c<=3; c++) {
           ptrstart = colors[c];
           
	   for(x = 0 ; x < width ; x++)
	   {
		*(ptrstart++) = gamma_table[*ptrstart];
    	   }
        }
}

