/*++ Copyright (c) 1996-1999 Microsoft Corporation Module Name: brush.c Abstract: DrvRealizeBrush Environment: Windows NT Unidrv driver Revision History: 05/14/97 -amandan- Created --*/ #include "unidrv.h" BRGBColorSpace(PDEV *); LONG FindCachedHTPattern( PDEV *pPDev, WORD wChecksum ) /*++ Routine Description: This function find the cached text brush pattern color, if not there then it will add it to the cached. Arguments: pPDev - Pointer to our PDEV wCheckSum - Checksum of pattern brush Return Value: LONG >0 - Found the cached, return value is the pattern ID =0 - Out of memory, not cached <0 - not in the cached, add to the cached, return value is the negated pattern ID Author: 08-Apr-1997 Tue 19:42:21 created -by- Daniel Chou (danielc) Revision History: --*/ { LPWORD pDBCache; WORD cMaxDB; WORD cUsedDB; WORD Index; // // The first is the cMaxDB, the 2nd is the cUsedDB // if (pDBCache = pPDev->GState.pCachedPatterns) { cMaxDB = *(pDBCache + 0); cUsedDB = *(pDBCache + 1); pDBCache += 2; for (Index = 1; Index <= cUsedDB; Index++, pDBCache++) { if (*pDBCache == wChecksum) { VERBOSE(("\n\tRaddd:FindCachedHTPat(%04lx): FOUND=%ld ", wChecksum, Index)); return((LONG)Index); } } // // If we can't find a cached one, add the new one to the list // if (cUsedDB < cMaxDB) { *pDBCache = wChecksum; *(pPDev->GState.pCachedPatterns + 1) += 1; VERBOSE(("\n\tRaddd:FindCachedHTPat(%04lx): NOT FOUND=%ld ", wChecksum, -(LONG)Index)); return(-(LONG)Index); } } else { cUsedDB = cMaxDB = 0; } // // We need to expand the checksum cached buffer // VERBOSE(("\n\tUnidrv:FindCachedHTPat(%04lx): pDBCache=%08lx, cUsedDB=%ld, cMaxDB=%ld", wChecksum, pDBCache, cUsedDB, cMaxDB)); if (((cMaxDB + DBCACHE_INC) < DBCACHE_MAX) && (pDBCache = (LPWORD)MemAllocZ((cMaxDB + DBCACHE_INC + 2) * sizeof(WORD)))) { if ((cMaxDB) && (pPDev->GState.pCachedPatterns)) { CopyMemory(pDBCache + 2, pPDev->GState.pCachedPatterns + 2, cMaxDB * sizeof(WORD)); MemFree(pPDev->GState.pCachedPatterns); } *(pDBCache + 0) = cMaxDB + DBCACHE_INC; *(pDBCache + 1) = cUsedDB + 1; *(pDBCache + 2 + cUsedDB) = wChecksum; pPDev->GState.pCachedPatterns = pDBCache; VERBOSE (("\n\tUnidrv:FindCachedHTPat(%04lx): pDBCache=%08lx, cUsedDB=%ld, cMaxDB=%ld, EMPTY=%ld ", wChecksum, pDBCache, *(pDBCache + 1), *(pDBCache + 0), -(LONG)(cUsedDB + 1))); return(-(LONG)(cUsedDB + 1)); } // // Out of memory // WARNING(("\n\tUnidrv:FindCachedHTPat: OUT OF MEMORY")); return(0); } BOOL Download1BPPHTPattern( PDEV *pPDev, SURFOBJ *pso, DWORD dwPatID ) /*++ Routine Description: This function donload a user define pattern Arguments: pPDev - Pointer to the PDEV pDevBrush - Pointer to the cached device brush Return Value: INT to indicate a pattern number downloaed/defined Author: 08-Apr-1997 Tue 19:41:00 created -by- Daniel Chou (danielc) Revision History: --*/ { SURFOBJ so; LPBYTE pb; LPBYTE pbEnd; LPBYTE pSrc; DWORD cbCX; DWORD cb; WORD cxcyRes; INT Len; BYTE Buf[64]; BYTE XorMask; BYTE EndMask; so = *pso; pb = Buf; pbEnd = pb + sizeof(Buf) - 4; cbCX = (DWORD)(((DWORD)so.sizlBitmap.cx + 7) >> 3); // // Update standard variable and send command // pPDev->dwPatternBrushType = BRUSH_USERPATTERN; pPDev->dwPatternBrushSize = (DWORD)(cbCX * so.sizlBitmap.cy) + 12; pPDev->dwPatternBrushID = dwPatID; WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, CMD_DOWNLOAD_PATTERN)); // // Send header and pattern data // *pb++ = 20; *pb++ = 0; *pb++ = (so.iBitmapFormat == BMF_1BPP) ? 1 : 8; *pb++ = 0; *pb++ = HIBYTE((WORD)so.sizlBitmap.cx); *pb++ = LOBYTE((WORD)so.sizlBitmap.cx); *pb++ = HIBYTE((WORD)so.sizlBitmap.cy); *pb++ = LOBYTE((WORD)so.sizlBitmap.cy); *pb++ = HIBYTE((WORD)pPDev->ptGrxRes.x); *pb++ = LOBYTE((WORD)pPDev->ptGrxRes.x); *pb++ = HIBYTE((WORD)pPDev->ptGrxRes.y); *pb++ = LOBYTE((WORD)pPDev->ptGrxRes.y); // // The XorMask is used to flip the BLACK/WHITE bit depends on the output // and EndMask is to mask off any unwanted bit in the last byte to 0 // this is to fix LJ5si, LJ4si firmware bugs, REMEMBER our palette always // in RGB additive mode so the passed in 1BPP format has 0=Black, 1=White // XorMask = (BRGBColorSpace(pPDev)) ? 0x00 : 0xff; if (!(EndMask = (BYTE)(0xff << (8 - (so.sizlBitmap.cx & 0x07))))) { EndMask = 0xff; } VERBOSE(("\n\tRaddd:DownLoaHTPattern: PatID=%ld, Format=%ld, %ld x %ld, XorMask=%02lx, EndMaks=%02lx\t\t", dwPatID, pso->iBitmapFormat, so.sizlBitmap.cx, so.sizlBitmap.cy, XorMask, EndMask)); while (so.sizlBitmap.cy--) { cb = cbCX; pSrc = so.pvScan0; (LPBYTE)so.pvScan0 += so.lDelta; while (cb--) { *pb++ = (BYTE)(*pSrc++ ^ XorMask); if (!cb) { *(pb - 1) &= EndMask; } if (pb >= pbEnd) { WriteSpoolBuf(pPDev, Buf, (DWORD)(pb - Buf)); pb = Buf; } } } // // Send remaining data // if (Len = (INT)(pb - Buf)) { WriteSpoolBuf(pPDev, Buf, Len); } return(TRUE); } WORD GetBMPChecksum( SURFOBJ *pso, PRECTW prcw ) /*++ Routine Description: Arguments: Return Value: Author: 22-Apr-1997 Tue 11:32:37 created -by- Daniel Chou (danielc) Revision History: --*/ { LPBYTE pb; RECTW rcw; LONG cy; LONG cPixels; LONG lDelta; WORD wChecksum; UINT c1stPixels; UINT Format; BYTE BegMask; BYTE EndMask; BYTE XorMask; rcw = *prcw; Format = (UINT)pso->iBitmapFormat; wChecksum = 0; VERBOSE(("\nComputeChecksum(%ld): (%4ld, %4ld)-(%4ld, %4ld)=%3ldx%3ld\t\t", Format, rcw.l, rcw.t, rcw.r, rcw.b, rcw.r - rcw.l, rcw.b - rcw.t)); if (rcw.l > (WORD)pso->sizlBitmap.cx) { rcw.l = (WORD)pso->sizlBitmap.cx; } if (rcw.t > (WORD)pso->sizlBitmap.cy) { rcw.t = (WORD)pso->sizlBitmap.cy; } if (rcw.r > (WORD)pso->sizlBitmap.cx) { rcw.r = (WORD)pso->sizlBitmap.cx; } if (rcw.b > (WORD)pso->sizlBitmap.cy) { rcw.b = (WORD)pso->sizlBitmap.cy; } if ((rcw.r <= rcw.l) || (rcw.b <= rcw.t)) { return(wChecksum); } cPixels = (LONG)(rcw.r - rcw.l); cy = (LONG)(rcw.b - rcw.t); lDelta = pso->lDelta; pb = (LPBYTE)pso->pvScan0 + ((LONG)rcw.t * lDelta); XorMask = 0xFF; // // rcw.r and rcw.b are exclusive // --rcw.r; --rcw.b; switch (Format) { case BMF_1BPP: pb += (rcw.l >> 3); c1stPixels = (UINT)(8 - (rcw.l & 0x07)); BegMask = (BYTE)(0xff >> (rcw.l & 0x07)); EndMask = (BYTE)(0xff << (8 - (rcw.r & 0x07))); break; case BMF_4BPP: if (rcw.l & 0x01) { BegMask = 0x07; c1stPixels = 4; } else { BegMask = 0x77; c1stPixels = 0; } pb += (rcw.l >> 1); cPixels <<= 2; EndMask = (BYTE)((rcw.r & 0x01) ? 0x70 : 0x77); XorMask = 0x77; break; case BMF_8BPP: case BMF_16BPP: case BMF_24BPP: BegMask = EndMask = 0xFF; c1stPixels = (UINT)(Format - BMF_8BPP + 1); pb += (rcw.l * c1stPixels); cPixels *= (c1stPixels << 3); c1stPixels = 0; break; } while (cy--) { LPBYTE pbCur; LONG Count; WORD w; pbCur = pb; pb += lDelta; Count = cPixels; w = (WORD)((c1stPixels) ? ((*pbCur++ ^ XorMask) & BegMask) : 0); if ((Count -= c1stPixels) >= 8) { do { w <<= 8; w |= (*pbCur++ ^ XorMask); wChecksum += w; } while ((Count -= 8) >= 8); } if (Count > 0) { w <<= 8; w |= (WORD)((*pbCur ^ XorMask) & EndMask); } else { w &= EndMask; } wChecksum += w; } VERBOSE(("\nComputeChecksum(%ld:%04lx): (%4ld, %4ld)-(%4ld, %4ld)=%3ldx%3ld [%3ld], pb=%08lx [%02lx:%02lx], %1ld\t", Format, wChecksum, rcw.l, rcw.t, rcw.r + 1, rcw.b + 1, rcw.r - rcw.l + 1, rcw.b - rcw.t + 1, cPixels, pb, BegMask, EndMask, c1stPixels)); return(wChecksum); } BOOL BRGBColorSpace( PDEV *pPDev ) { LISTNODE *pListNode = NULL; if (pPDev->pDriverInfo && pPDev->pColorModeEx) pListNode = LISTNODEPTR(pPDev->pDriverInfo,pPDev->pColorModeEx->liColorPlaneOrder); while (pListNode) { switch (pListNode->dwData) { case COLOR_RED: case COLOR_GREEN: case COLOR_BLUE: return TRUE; default: break; } if (pListNode->dwNextItem == END_OF_LIST) break; else pListNode = LOCALLISTNODEPTR(pPDev->pDriverInfo, pListNode->dwNextItem); } return FALSE; } BOOL BFoundCachedBrush( PDEV *pPDev, PDEVBRUSH pDevBrush ) { // // search the cache only if we want to use the last color. If // MODE_BRUSH_RESET_COLOR is set then we want to explicitly reset the brush // color by sending the command to the printer. // if ( (!(pPDev->ctl.dwMode & MODE_BRUSH_RESET_COLOR)) ) { if ( (pDevBrush->dwBrushType == pPDev->GState.CurrentBrush.dwBrushType) && (pDevBrush->iColor == pPDev->GState.CurrentBrush.iColor) ) { return TRUE; } } else { // // Reset the MODE_BRUSH_RESET_COLOR flag as we want to search the cache // next time. // pPDev->ctl.dwMode &= ~MODE_BRUSH_RESET_COLOR; } return FALSE; }