/*++ Copyright (c) 1996-1999 Microsoft Corporation Module Name: state.c Abstract: Printer graphics state tracking. Implemenation of GSRealizeBrush GSUnRealizeBrush GSSelectBrush GSResetBrush Environment: Windows NT Unidrv driver Revision History: 04/29/97 -amandan- Created --*/ #include "unidrv.h" #ifdef WINNT_40 // NT 4.0 extern HSEMAPHORE hSemBrushColor; LPDWORD pBrushSolidColor = NULL; DWORD GetBRUSHOBJRealColor( PDEV *pPDev, BRUSHOBJ *pbo ) /*++ Routine Description: Given a BRUSHOBJ Gets the original color ofthe brush using DrvDitherColor. Arguments: pPDev - Pointer to PDEV pbo - Pointer to BRUSHOBJ Return Value: Original RGB color Note: --*/ { DWORD SolidColor; if ((SolidColor = pbo->iSolidColor) == 0xFFFFFFFF) { SolidColor = 0; EngAcquireSemaphore(hSemBrushColor); pBrushSolidColor = &SolidColor; BRUSHOBJ_pvGetRbrush(pbo); EngReleaseSemaphore(hSemBrushColor); } else { ERR(( "GetBRUSHOBJRealColor: Should not be Called for mapped color\n" )); SolidColor = 0; } return(SolidColor); } #endif //WINNT_40 ULONG GetRGBColor(PDEV *, ULONG); PDEVBRUSH GSRealizeBrush( IN OUT PDEV *pPDev, IN SURFOBJ *pso, IN BRUSHOBJ *pbo ) /*++ Routine Description: Given a BRUSHOBJ perform one of the following: Color Printer: 1. Programmable Palette 2. Non-Programmable Palette Monochrome Printer: 1. User defined pattern, only if brush is pattern brush 2. Shading Patterns , only if brush is pattern brush 3. Maps to black/white brush 4. Maps to black Arguments: pPDev - Pointer to PDEV pso - Pointer to SURFOBJ pbo - Pointer to BRUSHOBJ Return Value: PDEVBRUSH if successful, otherwise NULL Note: It's up to the caller to call GSUnRealizeBrush to free brushes --*/ { ULONG ulColor = pbo->iSolidColor; PDEVBRUSH pDevBrush; BOOL bPatternBrush = FALSE; // // Allocate memory for Brush, deallocation is done in GSUnRealizeBrush // if ((pDevBrush = MemAllocZ(sizeof(DEVBRUSH))) == NULL) return NULL; if (pso->iBitmapFormat != BMF_24BPP && pbo->iSolidColor != DITHERED_COLOR) { // // Index case // pbo->iSolidColor holds the Index, Map index to RGB color // ulColor = GetRGBColor(pPDev, pbo->iSolidColor); } // // TBD: BUG_BUG NT4 - needs to be fixed // no NT4 bugs will be fixed unless necessary. // if (pbo->iSolidColor == DITHERED_COLOR) { // // Pattern Brush, get the color // #ifndef WINNT_40 //NT 5.0 ulColor = BRUSHOBJ_ulGetBrushColor(pbo); // BUG_BUG: Unidrv currently doesn't handle the case where the brush is // a non-solid brush (return -1). The HPGL / PCL-XL implementations will require // this so we will merge that implementation when it is complete. if (ulColor != -1) ulColor &= 0x00FFFFFF; #else // NT 4.0 ulColor = GetBRUSHOBJRealColor(pPDev, pbo); #endif //!WINNT_40 bPatternBrush = TRUE; } // // ulColor should always be RGB color by the time we get here // if ((pso->iBitmapFormat == BMF_1BPP) ) { // // Monochrome case // Download user define pattern or select intensity for // non-solid brush ONLY. Otherwise, map it to black or white. // // if ((pPDev->fMode & PF_DOWNLOAD_PATTERN) && bPatternBrush) { PDEVBRUSH pDB; // Support user defined pattern, iColor will hold the pattern ID if ((pDB = (PDEVBRUSH)BRUSHOBJ_pvGetRbrush(pbo)) == NULL) { WARNING(("BRUSHOBJ_pvGetRBrush failed")); MemFree(pDevBrush); return NULL; } pDevBrush->dwBrushType = BRUSH_USERPATTERN; pDevBrush->iColor = pDB->iColor; } else if ((pPDev->fMode & PF_SHADING_PATTERN) && bPatternBrush) { // Support shading pattern, iColor holds %of gray pDevBrush->dwBrushType = BRUSH_SHADING; pDevBrush->iColor = GET_SHADING_PERCENT(ulColor); } else if (pPDev->fMode & PF_WHITEBLACK_BRUSH) { // Support black/white brush commands, iColor will hold RBG color // We are here means solid color brush, and for monochrome // it can be either black or white. If it's indexed, we // have taken care of mapping index to RGB color already // pDevBrush->dwBrushType = BRUSH_BLKWHITE; pDevBrush->iColor = ulColor; } else { // // Map to black // pDevBrush->dwBrushType = BRUSH_BLKWHITE; pDevBrush->iColor = RGB_BLACK_COLOR; } } else if (pPDev->fMode & PF_ANYCOLOR_BRUSH ) { // // Programmable // pDevBrush->dwBrushType = BRUSH_PROGCOLOR; pDevBrush->iColor = ulColor; } else { // // Non-Programmable // pDevBrush->dwBrushType = BRUSH_NONPROGCOLOR; // // Since ulColor is RGB color, need to map it to the nearest // color in the fixed palette. // iColor will hold the index of the color // if (pbo->iSolidColor == DITHERED_COLOR) pDevBrush->iColor = BestMatchDeviceColor(pPDev,(DWORD)ulColor); else pDevBrush->iColor = pbo->iSolidColor; } // // Save the brush to the Realized Brush linked list // if (pPDev->GState.pRealizedBrush == NULL) { pDevBrush->pNext = NULL; pPDev->GState.pRealizedBrush = pDevBrush; } else { pDevBrush->pNext = pPDev->GState.pRealizedBrush; pPDev->GState.pRealizedBrush = pDevBrush; } return pDevBrush; } VOID GSUnRealizeBrush( IN PDEV *pPDev ) /*++ Routine Description: Deallocate memory for the realized brush Arguments: pPDev Pointer to PDEV Return Value: None --*/ { PDEVBRUSH pDevBrush = pPDev->GState.pRealizedBrush; VERBOSE(("GSUnRealizeBrush \n")); while(pPDev->GState.pRealizedBrush !=NULL) { pDevBrush = pPDev->GState.pRealizedBrush; pPDev->GState.pRealizedBrush = pDevBrush->pNext; MemFree(pDevBrush); } pPDev->GState.pRealizedBrush = NULL; } BOOL GSSelectBrush( IN PDEV *pPDev, IN PDEVBRUSH pDevBrush ) /*++ Routine Description: Given a pDevBrush, select the brush. Arguments: pPDev - Pointer to PDEV pDevBrush - Pointer to DEVBRUSH Return Value: TRUE if sucessful, otherwise FALSE --*/ { BOOL bIndexedColor = FALSE; // // Find Cached Brush, if the current selected brush matches // the caller request, do nothing. // if (BFoundCachedBrush(pPDev, pDevBrush)) return TRUE; switch(pDevBrush->dwBrushType){ case BRUSH_PROGCOLOR: { VERBOSE(("Using Programmable RGB Color \n")); if (((PAL_DATA *)pPDev->pPalData)->fFlags & PDF_PALETTE_FOR_8BPP_MONO) pDevBrush->iColor = ConvertRGBToGrey(pDevBrush->iColor); if ( !BSelectProgrammableBrushColor(pPDev, pDevBrush->iColor) ) { WARNING(("\nCan't Select the brush color for RGB = 0x%x\n",pDevBrush->iColor)); pDevBrush->iColor = BestMatchDeviceColor(pPDev, pDevBrush->iColor); bIndexedColor = TRUE; } } // // Let it fall thru to catch the indexed case // case BRUSH_NONPROGCOLOR: { if (bIndexedColor || pDevBrush->dwBrushType == BRUSH_NONPROGCOLOR) { INT iCmd; VERBOSE(("Using Non Programmable Indexed Color")); // // If this color is not supported, use the default color: black. // pDevBrush->iColor &= (MAX_COLOR_SELECTION - 1); /* 16 entry palette wrap around */ // // If there is no command to set the color, map to black. // if(COMMANDPTR(pPDev->pDriverInfo, CMD_COLORSELECTION_FIRST + pDevBrush->iColor) == NULL) pDevBrush->iColor = BLACK_COLOR_CMD_INDEX; iCmd = CMD_COLORSELECTION_FIRST + pDevBrush->iColor; WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, iCmd)); } } break; case BRUSH_USERPATTERN: { VERBOSE(("Selecting user defined pattern brush")); // // The pattern ID, is stored in pDevBrush->iColor // pPDev->dwPatternBrushType = BRUSH_USERPATTERN; pPDev->dwPatternBrushID = pDevBrush->iColor; WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, CMD_SELECT_PATTERN)); } break; case BRUSH_SHADING: { VERBOSE(("Selecting shading pattern brush")); // // The gray level (expressed as intensity) is stored in // pDevBrush->iColor // // // Update standard variable for brush selection command // pPDev->dwPatternBrushType = BRUSH_SHADING; pPDev->dwPatternBrushID = pDevBrush->iColor; WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, CMD_SELECT_PATTERN)); } break; case BRUSH_BLKWHITE: { INT iCmd; if (pDevBrush->iColor == RGB_WHITE_COLOR) { VERBOSE(("Selecting white brush")); // // BUG_BUG, need to remove the CMD_WHITETEXTON and CMD_WHITETEXTOFF // once all GPD changes have been made for BLACKBRUSH, WHITEBRUSH // doesn't hurt to leave it in. if (pPDev->arCmdTable[CMD_SELECT_WHITEBRUSH]) iCmd = CMD_SELECT_WHITEBRUSH; else iCmd = CMD_WHITETEXTON; } else { // // Black - standard text color // VERBOSE(("Selecting black brush")); // // BUG_BUG, need to remove the CMD_WHITETEXT_ON and CMD_WHITETEXT_OFF // once all GPD changes have been made for BLACKBRUSH, WHITEBRUSH // doesn't hurt to leave it in. // if (pPDev->arCmdTable[CMD_SELECT_BLACKBRUSH]) iCmd = CMD_SELECT_BLACKBRUSH; else iCmd = CMD_WHITETEXTOFF; } // // Set the desired colour ! // WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, iCmd)); } break; } // // Cached the brush // CACHE_CURRENT_BRUSH(pPDev, pDevBrush) return TRUE; } VOID GSResetBrush( IN OUT PDEV *pPDev ) /*++ Routine Description: Select the default brush Arguments: pPDev - Pointer to PDEV Return Value: None --*/ { DEVBRUSH DeviceBrush; PDEVBRUSH pDevBrush = &DeviceBrush; PAL_DATA *pPD; pPD = pPDev->pPalData; if (pPD->fFlags & PDF_PALETTE_FOR_1BPP) { // // Monochrome case. Select black brush // pDevBrush->dwBrushType = BRUSH_BLKWHITE; pDevBrush->iColor = RGB_BLACK_COLOR; if (BFoundCachedBrush(pPDev, pDevBrush)) return; // // BUG_BUG, need to remove the CMD_WHITETEXT_ON and CMD_WHITETEXT_OFF // once all GPD changes have been made // doesn't hurt to leave it in. // if (pPDev->arCmdTable[CMD_SELECT_BLACKBRUSH]) WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, CMD_SELECT_BLACKBRUSH)); else WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, CMD_WHITETEXTOFF)); } else if (pPDev->fMode & PF_ANYCOLOR_BRUSH ) { // // Programmable // pDevBrush->dwBrushType = BRUSH_PROGCOLOR; pDevBrush->iColor = RGB_BLACK_COLOR; VResetProgrammableBrushColor(pPDev); } else { // // Non-Programmable // pDevBrush->dwBrushType = BRUSH_NONPROGCOLOR; pDevBrush->iColor = ((PAL_DATA*)(pPDev->pPalData))->iBlackIndex; if (BFoundCachedBrush(pPDev, pDevBrush)) return; WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo,CMD_SELECTBLACKCOLOR)); } CACHE_CURRENT_BRUSH(pPDev, pDevBrush) } ULONG GetRGBColor( IN PDEV *pPDev, IN ULONG ulIndex ) /*++ Routine Description: Given an Indexed color, map to an RGB color Arguments: pPDev - Pointer to PDEV pDevBrush - Pointer to DEVBRUSH Return Value: TRUE if sucessful, otherwise FALSE --*/ { // If the index is invalid, map to Black. if (ulIndex > PALETTE_MAX) { ERR(( "GSSelectBrush: Bad input Color Index\n" )); ulIndex = ((PAL_DATA*)(pPDev->pPalData))->iBlackIndex; } return( ((PAL_DATA *)(pPDev->pPalData))->ulPalCol[ulIndex]); }