/*++ Copyright (c) 1996-1999 Microsoft Corporation Module Name: cmdcb.c Abstract: Implementation of GPD command callback for "test.gpd": OEMCommandCallback Environment: Windows NT Unidrv driver Revision History: // NOTICE-2002/03/20-v-sueyas- // 04/07/97 -zhanw- // Created it. --*/ #include "pdev.h" // #289908: pOEMDM -> pdevOEM PDEVOEM APIENTRY OEMEnablePDEV( PDEVOBJ pdevobj, PWSTR pPrinterName, ULONG cPatterns, HSURF *phsurfPatterns, ULONG cjGdiInfo, GDIINFO *pGdiInfo, ULONG cjDevInfo, DEVINFO *pDevInfo, DRVENABLEDATA *pded) { // NTRAID#NTBUG9-581725-2002/03/20-v-sueyas-: Check for illegal parameters if (NULL == pdevobj) { ERR(("OEMEnablePDEV: Invalid parameter(s).\n")); return NULL; } if(!pdevobj->pdevOEM) { if(!(pdevobj->pdevOEM = MemAllocZ(sizeof(QPLKPDEV)))) { return NULL; } } return pdevobj->pdevOEM; } VOID APIENTRY OEMDisablePDEV( PDEVOBJ pdevobj) { // NTRAID#NTBUG9-581725-2002/03/20-v-sueyas-: Check for illegal parameters if (NULL == pdevobj) { ERR(("OEMDisablePDEV: Invalid parameter(s).\n")); return; } if(pdevobj->pdevOEM) { MemFree(pdevobj->pdevOEM); pdevobj->pdevOEM = NULL; } } BOOL APIENTRY OEMResetPDEV( PDEVOBJ pdevobjOld, PDEVOBJ pdevobjNew) { PQPLKPDEV pOEMOld, pOEMNew; // NTRAID#NTBUG9-581725-2002/03/20-v-sueyas-: Check for illegal parameters if (NULL == pdevobjOld || NULL == pdevobjNew) { ERR(("OEMResetPDEV: Invalid parameter(s).\n")); return FALSE; } pOEMOld = (PQPLKPDEV)pdevobjOld->pdevOEM; pOEMNew = (PQPLKPDEV)pdevobjNew->pdevOEM; if (pOEMOld != NULL && pOEMNew != NULL) *pOEMNew = *pOEMOld; return TRUE; } // BInitOEMExtraData() and BMergeOEMExtraData() has moved to common.c // ####### #define WRITESPOOLBUF(p, s, n) \ ((p)->pDrvProcs->DrvWriteSpoolBuf(p, s, n)) #define PARAM(p,n) \ (*((p)+(n))) // Private Definition // Command callback #define CMD_BEGINPAGE_DELTAROW 1 #define CMD_SENDBLOCKDATA_DELTAROW 2 #define CMD_SENDBLOCKDATA_B2 3 #define CMD_BEGINPAGE_B2 4 // Color support #define CMD_BEGINPAGE_C1 5 #define CMD_BEGINPAGE_DEFAULT 6 #define CMD_BEGINPAGE_B2_LAND 7 // Special fix for Qnix Picasso 300 #define CMD_BEGINPAGE_B2_PICA 8 #define CMD_CR 10 #define CMD_LF 11 #define CMD_FF 12 // Color support #define CMD_SELECT_CYAN 100 #define CMD_SELECT_MAGENTA 101 #define CMD_SELECT_YELLOW 102 #define CMD_SELECT_BLACK 103 #define CMD_YMOVE_REL_COLOR 150 // #299937: Incorrect value for Y Move #define COLOR_MASTERUNIT 600 // Compression Type #define COMP_DELTARAW 1 #define COMP_B2 2 #define COMP_NOCOMP 3 // Compression routine WORD DeltaRawCompress(PBYTE, PBYTE, PBYTE, DWORD, DWORD); WORD B2Compress(PBYTE, PBYTE, PBYTE, DWORD); PBYTE RLE_comp(PBYTE); WORD RLEencoding(PBYTE, PBYTE, DWORD); /*****************************************************************************/ /* */ /* BOOL APIENTRY OEMFilterGraphics( */ /* PDEVOBJ pdevobj */ /* PBYTE pBuf */ /* DWORD dwLen ) */ /* */ /*****************************************************************************/ BOOL APIENTRY OEMFilterGraphics( PDEVOBJ pdevobj, // Points to private data required by the Unidriver.dll PBYTE pBuf, // points to buffer of graphics data DWORD dwLen) // length of buffer in bytes { BYTE CompressedScanLine[COMPRESS_BUFFER_SIZE]; BYTE HeaderScanLine[4]; WORD nCompBufLen; PQPLKPDEV pOEM; // Color support PDWORD pdwLastScanLineLen; LPSTR lpLastScanLine; BYTE HeaderColorPlane; // NTRAID#NTBUG9-581725-2002/03/20-v-sueyas-: Check for illegal parameters if (NULL == pdevobj || NULL == pBuf || 0 == dwLen) { ERR(("OEMFilterGraphics: Invalid parameter(s).\n")); return FALSE; } pOEM = (PQPLKPDEV)pdevobj->pdevOEM; // NTRAID#NTBUG9-581725-2002/03/20-v-sueyas-: Check for null pointers if (NULL == pOEM) { ERR(("OEMFilterGraphics: pdevobj->pdevOEM = 0.\n")); return FALSE; } if (pOEM->bFirst) { // Color support ZeroMemory(pOEM->lpCyanLastScanLine, sizeof pOEM->lpCyanLastScanLine ); ZeroMemory(pOEM->lpMagentaLastScanLine, sizeof pOEM->lpMagentaLastScanLine ); ZeroMemory(pOEM->lpYellowLastScanLine, sizeof pOEM->lpYellowLastScanLine ); ZeroMemory(pOEM->lpBlackLastScanLine, sizeof pOEM->lpBlackLastScanLine ); pOEM->bFirst = FALSE; } // Color support switch (pOEM->fColor) { case CC_CYAN: HeaderColorPlane = 0x05; pdwLastScanLineLen = &(pOEM->dwCyanLastScanLineLen); lpLastScanLine = pOEM->lpCyanLastScanLine; break; case CC_MAGENTA: HeaderColorPlane = 0x06; pdwLastScanLineLen = &(pOEM->dwMagentaLastScanLineLen); lpLastScanLine = pOEM->lpMagentaLastScanLine; break; case CC_YELLOW: HeaderColorPlane = 0x07; pdwLastScanLineLen = &(pOEM->dwYellowLastScanLineLen); lpLastScanLine = pOEM->lpYellowLastScanLine; break; case CC_BLACK: default: // Black&White HeaderColorPlane = 0x04; pdwLastScanLineLen = &(pOEM->dwBlackLastScanLineLen); lpLastScanLine = pOEM->lpBlackLastScanLine; break; } if(pOEM->dwCompType == COMP_DELTARAW) { nCompBufLen = (WORD)DeltaRawCompress(pBuf, lpLastScanLine, CompressedScanLine, (*pdwLastScanLineLen > dwLen) ? *pdwLastScanLineLen : dwLen, (DWORD)0); HeaderScanLine[0] = 0; HeaderScanLine[1] = 0; HeaderScanLine[2] = HIBYTE(nCompBufLen); HeaderScanLine[3] = LOBYTE(nCompBufLen); WRITESPOOLBUF(pdevobj, (PBYTE) HeaderScanLine, 4); WRITESPOOLBUF(pdevobj, (PBYTE) CompressedScanLine, nCompBufLen); if( dwLen > SCANLINE_BUFFER_SIZE ) return FALSE; CopyMemory(lpLastScanLine, pBuf, dwLen); if (*pdwLastScanLineLen > dwLen) { if(*pdwLastScanLineLen > SCANLINE_BUFFER_SIZE ) return FALSE; ZeroMemory(lpLastScanLine + dwLen, *pdwLastScanLineLen - dwLen); } *pdwLastScanLineLen = dwLen; } else if(pOEM->dwCompType == COMP_B2) { nCompBufLen = B2Compress(lpLastScanLine, pBuf, CompressedScanLine, (*pdwLastScanLineLen > dwLen) ? *pdwLastScanLineLen : dwLen); // send color plane command if (pOEM->bColor) WRITESPOOLBUF(pdevobj, &HeaderColorPlane, 1); HeaderScanLine[0] = 0x02; HeaderScanLine[1] = (BYTE) (nCompBufLen >> 8); HeaderScanLine[2] = (BYTE) nCompBufLen; WRITESPOOLBUF(pdevobj, (PBYTE) HeaderScanLine, 3); // #297256: Line is cut and increase // Do not send if no compressed data. if (nCompBufLen) { WRITESPOOLBUF(pdevobj, (PBYTE) CompressedScanLine, nCompBufLen); *pdwLastScanLineLen = dwLen; } } return TRUE; } /*****************************************************************************/ /* */ /* INT APIENTRY OEMCommandCallback( */ /* PDEVOBJ pdevobj */ /* DWORD dwCmdCbId */ /* DWORD dwCount */ /* PDWORD pdwParams */ /* */ /*****************************************************************************/ INT APIENTRY OEMCommandCallback( PDEVOBJ pdevobj, // Points to private data required by the Unidriver.dll DWORD dwCmdCbId, // Callback ID DWORD dwCount, // Counts of command parameter PDWORD pdwParams) // points to values of command params { PQPLKPDEV pOEM; INT iRet = 0; // Color support DWORD count, n, unit; BYTE aCmd[32]; // NTRAID#NTBUG9-581725-2002/03/20-v-sueyas-: Check for illegal parameters if (NULL == pdevobj) { ERR(("OEMCommandCallback: Invalid parameter(s).\n")); return 0; } pOEM = (PQPLKPDEV)(pdevobj->pdevOEM); // NTRAID#NTBUG9-581725-2002/03/20-v-sueyas-: Check for null pointers if (NULL == pOEM) { ERR(("OEMCommandCallback: pdevobj->pdevOEM = 0.\n")); return 0; } switch(dwCmdCbId) { case CMD_BEGINPAGE_DEFAULT: WRITESPOOLBUF(pdevobj, "\033}0;0;5B", 8); pOEM->bFirst = TRUE; break; case CMD_BEGINPAGE_DELTAROW: WRITESPOOLBUF(pdevobj, "\033}0;0;3B", 8); pOEM->bFirst = TRUE; break; case CMD_BEGINPAGE_B2: case CMD_BEGINPAGE_B2_PICA: WRITESPOOLBUF(pdevobj, "\033}0;0;4B", 8); pOEM->bFirst = TRUE; if (dwCmdCbId == CMD_BEGINPAGE_B2_PICA ) { if (pdwParams[0] == 300 ) WRITESPOOLBUF(pdevobj, "\x00\x1C", 2); else WRITESPOOLBUF(pdevobj, "\x00\x38", 2); } break; case CMD_BEGINPAGE_B2_LAND: WRITESPOOLBUF(pdevobj, "\033}0;0;7B", 8); pOEM->bFirst = TRUE; break; // Color support case CMD_BEGINPAGE_C1: WRITESPOOLBUF(pdevobj, "\033}0;0;6B", 8); // #315089: some lines isn't printed on printable area test. // move cursor to printable origin. WRITESPOOLBUF(pdevobj, "\x05\x00\x03\x06\x00\x03\x07\x00\x03\x04\x00\x03", 12); pOEM->bFirst = TRUE; pOEM->dwCompType = COMP_B2; pOEM->bColor = TRUE; break; case CMD_SENDBLOCKDATA_DELTAROW: pOEM->dwCompType = COMP_DELTARAW; break; case CMD_SENDBLOCKDATA_B2: pOEM->dwCompType = COMP_B2; break; case CMD_CR: case CMD_LF: case CMD_FF: // Dummy support break; // Color support case CMD_SELECT_CYAN: pOEM->fColor = CC_CYAN; break; case CMD_SELECT_MAGENTA: pOEM->fColor = CC_MAGENTA; break; case CMD_SELECT_YELLOW: pOEM->fColor = CC_YELLOW; break; case CMD_SELECT_BLACK: pOEM->fColor = CC_BLACK; break; case CMD_YMOVE_REL_COLOR: // #299937: Incorrect value for Y Move // YMove value is always in MasterUnit even YMoveUnit was specified. if (dwCount < 2 || !pdwParams) break; // NTRAID#NTBUG9-581725-2002/03/20-v-sueyas-: Check for deviding by zero if (0 == pdwParams[1]) return 0; unit = COLOR_MASTERUNIT / pdwParams[1]; if (unit == 0) unit = 1; // for our safety count = pdwParams[0] / unit; while (count > 0) { n = min(count, 255); aCmd[0] = 0x04; aCmd[1] = 0x00; aCmd[2] = (BYTE)n; aCmd[3] = 0x05; aCmd[4] = 0x00; aCmd[5] = (BYTE)n; aCmd[6] = 0x06; aCmd[7] = 0x00; aCmd[8] = (BYTE)n; aCmd[9] = 0x07; aCmd[10] = 0x00; aCmd[11] = (BYTE)n; WRITESPOOLBUF(pdevobj, aCmd, 12); count -= n; } iRet = pdwParams[0]; break; default: break; } return iRet; } /************************************************* * * Image Delta Compression Routine * *=================================================== * Input: * nbyte : # of byte, raw data * Image_string: pointer of raw data * Prn_string : pointer of compress data * Output: * Ret_count : # of byte, compress data **************************************************/ WORD DeltaRawCompress( PBYTE Image_string, /* pointer to original string */ PBYTE ORG_image, /* pointer to previous scanline's string */ PBYTE Prn_string, /* pointer to return string */ DWORD nbyte, /* original number of bytes */ DWORD nMagics) //Magic number { DWORD c, Ret_count, Skip_flag, Skip_count; DWORD i, j, k, outcount; PBYTE Diff_ptr; PBYTE ORG_ptr; PBYTE Skip_ptr; BYTE Diff_byte; BYTE Diff_mask[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; BOOL bstart = TRUE; outcount = 0; Ret_count = 0; ORG_ptr = ORG_image; Skip_flag = TRUE; Skip_ptr = Prn_string++; Skip_count = (nMagics / 8) / 8; *Skip_ptr = (BYTE)Skip_count; k = (nbyte + 7) / 8; for(i = 0; i < k; i++) { Diff_byte = 0; Diff_ptr = Prn_string++; for(j = 0; j < 8; j++) { if ( (i * 8 + j) >= nbyte ) { *Prn_string++= 0; Diff_byte |= Diff_mask[j]; outcount++; } else { c = *Image_string++; if(c != *ORG_ptr) { *ORG_ptr++ = (BYTE)c; *Prn_string++= (BYTE)c; Diff_byte |= Diff_mask[j]; outcount++; } else { ORG_ptr++; } } } if(Diff_byte == 0) { if(Skip_flag == TRUE) { Skip_count++; Prn_string--; }else{ *Diff_ptr = Diff_byte; outcount++; } }else{ if(Skip_flag == TRUE) { Skip_flag = FALSE; *Skip_ptr = (BYTE)Skip_count; outcount++; *Diff_ptr = Diff_byte; outcount++; }else{ *Diff_ptr = Diff_byte; outcount++; } Ret_count = outcount; } } return (WORD)Ret_count; } /*****************************************************************************/ /* */ /* WORD B2Compress( */ /* PBYTE pLastScanLine */ /* PBYTE pCurrentScanLine */ /* PBYTE pPrnBuf */ /* DWORD nImageWidth */ /* */ /*****************************************************************************/ WORD B2Compress( PBYTE pLastScanLine, PBYTE pCurrentScanLine, PBYTE pPrnBuf, DWORD nImageWidth) { PBYTE pLast, pCurrent, pComp; PBYTE pByteNum, pCountByte; WORD i; BYTE nSameCount, nDiffCount; // #297256: Line is cut and increase // Indicate to zero if this place doesn't have any data. if (nImageWidth == 0) return 0; pLast = pLastScanLine; pCurrent = pCurrentScanLine; pComp = pPrnBuf; pByteNum = pComp; nSameCount = 0; nDiffCount = 0; pCountByte = pComp++; for(i = 0; i < nImageWidth; i++) { if(*pCurrent != *pLast) { nDiffCount++; if(nSameCount) // if continuous data remain... { *pCountByte = nSameCount; pCountByte = pComp++; nSameCount = 0; } if(nDiffCount > 127) { *pCountByte = 127 + 128; pComp = RLE_comp(pCountByte); pCountByte = pComp++; nDiffCount -= 127; } *pLast = *pCurrent; *pComp++ = *pCurrent; } else { nSameCount++; if(nDiffCount) // if non-continuous data remain... { *pCountByte = nDiffCount + 128; pComp = RLE_comp(pCountByte); pCountByte = pComp++; nDiffCount = 0; } if(nSameCount > 127) { *pCountByte = 127; pCountByte = pComp++; nSameCount -= 127; } } pCurrent++; pLast++; } // end of for loop if(nSameCount) *pCountByte = nSameCount; if(nDiffCount) { *pCountByte = nDiffCount+128; pComp = RLE_comp(pCountByte); } return((WORD) (pComp - pByteNum)); } /*****************************************************************************/ /* */ /* PBYTE RLE_comp(LPBYTE p) */ /* */ /*****************************************************************************/ PBYTE RLE_comp(PBYTE p) { WORD i, count, RLEEncodedCount; PBYTE p1; BYTE RLEBuffer[COMPRESS_BUFFER_SIZE]; count = (WORD) (*p - 128); if(count > 4) { RLEEncodedCount = RLEencoding(p + 1, (PBYTE) RLEBuffer, count); if(RLEEncodedCount < count) { *p++ = 0; // RLE encode indicator *p++ = (BYTE) RLEEncodedCount; p1 = RLEBuffer; for(i = 0; i < RLEEncodedCount; i++) *p++ = *p1++; return(p); } } return(p + 1 + count); } /*****************************************************************************/ /* */ /* WORD RLEencoding( */ /* PBYTE pCurrent */ /* PBYTE pComp */ /* DWORD count */ /* */ /*****************************************************************************/ WORD RLEencoding( PBYTE pCurrent, PBYTE pComp, DWORD count) { WORD i, nByteNum; BYTE curr, next, RLEcount; nByteNum = 0; RLEcount = 1; // NTRAID#NTBUG9-581725-2002/03/20-v-sueyas-: Initialize un-initialized variable next = 0; for(i = 0; i < count - 1; i++) { curr = *pCurrent++; next = *pCurrent; if(curr == next) { if(RLEcount == 255) { *pComp++ = RLEcount; *pComp++ = curr; nByteNum += 2; RLEcount = 1; } else { RLEcount++; } } else { *pComp++ = RLEcount; *pComp++ = curr; nByteNum += 2; RLEcount = 1; } } *pComp++ = RLEcount; *pComp++ = next; nByteNum += 2; return(nByteNum); }