1184 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1184 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /******************************Module*Header*******************************\
 | ||
| * Module Name: brushddi.cxx
 | ||
| *
 | ||
| * This provides the call backs necesary for brush realization.
 | ||
| *
 | ||
| * Created: 25-Apr-1991 20:59:49
 | ||
| * Author: Patrick Haluptzok patrickh
 | ||
| *
 | ||
| * Copyright (c) 1990-1999 Microsoft Corporation
 | ||
| \**************************************************************************/
 | ||
| 
 | ||
| #include "precomp.hxx"
 | ||
| 
 | ||
| BOOL
 | ||
| EngRealizeBrush(
 | ||
|     BRUSHOBJ *pbo,
 | ||
|     SURFOBJ  *psoTarget,
 | ||
|     SURFOBJ  *psoPattern,
 | ||
|     SURFOBJ  *psoMask,
 | ||
|     XLATEOBJ *pxlo,
 | ||
|     ULONG    iHatch
 | ||
|     );
 | ||
| 
 | ||
| BOOL
 | ||
| bGetRealizedBrush(
 | ||
|     BRUSH *pbrush,
 | ||
|     EBRUSHOBJ *pebo,
 | ||
|     PFN_DrvRealizeBrush pfnDrv
 | ||
|     );
 | ||
| 
 | ||
| 
 | ||
| #if DBG
 | ||
| ULONG dbrushalloc = 0, dbrushcachecheck = 0;
 | ||
| ULONG dbrushcachegrabbed = 0, dbrushcachehit = 0;
 | ||
| #endif
 | ||
| 
 | ||
| 
 | ||
| /******************************Public*Routine******************************\
 | ||
| * BRUSHOBJ_pvAllocRbrush
 | ||
| *
 | ||
| * Allocates memory for the driver's realization of a brush.  This is always
 | ||
| * called by the driver, never by the engine.
 | ||
| *
 | ||
| * History:
 | ||
| *  25-Apr-1991 -by- Patrick Haluptzok patrickh
 | ||
| * Wrote it.
 | ||
| \**************************************************************************/
 | ||
| 
 | ||
| PVOID
 | ||
| BRUSHOBJ_pvAllocRbrush(
 | ||
|     BRUSHOBJ *pbo, ULONG cj
 | ||
|     )
 | ||
| {
 | ||
|     ASSERTGDI(cj != 0, "ERROR GDI BRUSHOBJ_pvAllocRbrush cj = 0");
 | ||
|     ASSERTGDI(pbo->iSolidColor == 0xFFFFFFFF,
 | ||
|             "ERROR GDI BRUSHOBJ_pvAllocRbrush solid color brush passed in");
 | ||
| 
 | ||
|     DBRUSH *pdbrush;
 | ||
| 
 | ||
| #if DBG
 | ||
|     dbrushalloc++;
 | ||
| #endif
 | ||
| 
 | ||
|     //
 | ||
|     // If there's a cached DBRUSH, try to use it instead of allocating
 | ||
|     //
 | ||
|     if (gpCachedDbrush != NULL)
 | ||
|     {
 | ||
| 
 | ||
| #if DBG
 | ||
|         dbrushcachecheck++;
 | ||
| #endif
 | ||
|         //
 | ||
|         // Try to grab the cached DBRUSH
 | ||
|         //
 | ||
| 
 | ||
|         if ((pdbrush =
 | ||
|                 (PDBRUSH) InterlockedExchangePointer((PVOID *)&gpCachedDbrush,
 | ||
|                                               NULL))
 | ||
|                 != NULL)
 | ||
|         {
 | ||
| 
 | ||
| #if DBG
 | ||
|         dbrushcachegrabbed++;
 | ||
| #endif
 | ||
| 
 | ||
|             //
 | ||
|             // Got the cached DBRUSH; see if it's big enough
 | ||
|             //
 | ||
|             // Note: -4 because we define the realization buffer start as aj[0]
 | ||
|             //
 | ||
| 
 | ||
|             if (pdbrush->ulSizeGet() >= (sizeof(DBRUSH) - 4 + cj))
 | ||
|             {
 | ||
| 
 | ||
| #if DBG
 | ||
|                 dbrushcachehit++;
 | ||
| #endif
 | ||
|                 //
 | ||
|                 // It's big enough, so we'll use it and we're done
 | ||
|                 //
 | ||
|                 return(pbo->pvRbrush = pdbrush->aj);
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 //
 | ||
|                 // Not big enough; free it and do a normal allocation
 | ||
|                 //
 | ||
|                 VFREEMEM(pdbrush);
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     // Note: -4 because we define the realization buffer start as aj[0]
 | ||
|     if ((pdbrush = (DBRUSH *)PALLOCMEM(ULONGSIZE_T(sizeof(DBRUSH) - 4 + cj),'rbdG'))
 | ||
|             != NULL)
 | ||
|     {
 | ||
|         //
 | ||
|         // Remember the size of the allocation, for caching.
 | ||
|         //
 | ||
|         pdbrush->ulSizeSet(sizeof(DBRUSH) - 4 + cj);
 | ||
| 
 | ||
|         return(pbo->pvRbrush = pdbrush->aj);
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|         WARNING("Failed memory alloc BRUSHOBJ_pvAllocRbrush\n");
 | ||
|         return(NULL);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| //
 | ||
| // User mode printer driver support
 | ||
| //
 | ||
| 
 | ||
| PVOID
 | ||
| BRUSHOBJ_pvAllocRbrushUMPD(
 | ||
|     BRUSHOBJ    *pbo,
 | ||
|     ULONG       cj
 | ||
|     )
 | ||
| 
 | ||
| {
 | ||
|     if (pbo->pvRbrush == NULL)
 | ||
|     {
 | ||
|         DBRUSH  *pdbrush;
 | ||
| 
 | ||
|         cj += MAGIC_DBR_DIFF;
 | ||
| 
 | ||
|         if (pdbrush = (DBRUSH *) EngAllocUserMem(cj, UMPD_MEMORY_TAG))
 | ||
|         {
 | ||
|             pdbrush->ulSizeSet(cj);
 | ||
|             pdbrush->bMultiBrush(FALSE);
 | ||
|             pdbrush->bUMPDRBrush(TRUE);
 | ||
| 
 | ||
|             pbo->pvRbrush = pdbrush->aj;
 | ||
|         }
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|         RIP("BRUSHOBJ_pvAllocRbrush when pvRbrush is not NULL\n");
 | ||
|     }
 | ||
| 
 | ||
|     return pbo->pvRbrush;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| /******************************Public*Routine******************************\
 | ||
| * vTryToCacheRealization
 | ||
| *
 | ||
| * Attempt to cache the realization pointed to by pdbrush and described by pebo
 | ||
| * in the logical brush pointed to by pbrush. The way this works is that only
 | ||
| * the first realization of the logical brush can be cached. crFore is the key
 | ||
| * that indicates when the cached realization is valid. If crFore is not -1 when
 | ||
| * the logical brush is being realized, we just go realize the brush; if it's
 | ||
| * not -1, we check the cache ID fields to see if we can use the cached fields.
 | ||
| * InterlockedExchange() is used below to set crFore to make sure the cache ID
 | ||
| * fields are set before crFore. bCacheGrabbed() is used to protect the setting
 | ||
| * of the cache ID fields; once it's set, no one else can modify the cache ID
 | ||
| * fields, but no one else will try to use them until crFore is not -1.
 | ||
| *
 | ||
| * Also initializes the reference count in the realization to indicates either
 | ||
| * 1 or 2 current uses, depending on whether caching took place.
 | ||
| *
 | ||
| * History:
 | ||
| *  31-Oct-1993 -by- Michael Abrash [mikeab]
 | ||
| * Wrote it.
 | ||
| \**************************************************************************/
 | ||
| 
 | ||
| VOID
 | ||
| vTryToCacheRealization(
 | ||
|     EBRUSHOBJ *pebo,
 | ||
|     PRBRUSH prbrush,
 | ||
|     PBRUSH pbrush,
 | ||
|     BOOL bType
 | ||
|     )
 | ||
| {
 | ||
| // Reference count the realization once for being selected into this DC. This
 | ||
| // assumes we won't succeed in caching the brush next; if we do, we do a double
 | ||
| // reference count, once for caching in the logical brush and once for
 | ||
| // selecting into the DC
 | ||
| 
 | ||
|     prbrush->cRef(1);
 | ||
| 
 | ||
| // See if we can cache this realization in the logical brush; we can't if
 | ||
| // another realization has already been cached in the logical brush
 | ||
| 
 | ||
|     if ( !pbrush->bCacheGrabbed() )
 | ||
|     {
 | ||
| 
 | ||
|     // Try to grab the "can cache" flag; if we don't get it, someone just
 | ||
|     // sneaked in and got it ahead of us, so we're out of luck and can't cache
 | ||
| 
 | ||
|         if ( pbrush->bGrabCache() )
 | ||
|         {
 | ||
| 
 | ||
|         // We got the "can cache" flag, so now we can cache this realization
 | ||
|         // in the logical brush
 | ||
| 
 | ||
|         // It's cached in the brush, so it won't be deleted until the logical
 | ||
|         // brush goes away and it's not selected into any DCs, so reference
 | ||
|         // count the realization again. We don't need to do an
 | ||
|         // InterlockedIncrement here because until crFore is set, no one else
 | ||
|         // can get at this realization. InterlockedExchange() is used below to
 | ||
|         // set crFore to make sure the reference count is set before anyone
 | ||
|         // else can see the caching info
 | ||
| 
 | ||
|             prbrush->cRef(2);
 | ||
| 
 | ||
|         // These cache ID fields must be set before crFore, because crFore
 | ||
|         // is the key that indicates when the cached realization is valid.
 | ||
|         // If crFore is -1 when the logical brush is being realized, we
 | ||
|         // just go realize the brush; if it's not -1, we check the cache ID
 | ||
|         // fields to see if we can use the cached fields.
 | ||
|         // InterlockedExchange() is used below to set crFore to make sure
 | ||
|         // the cache ID fields are set before crFore
 | ||
| 
 | ||
|             if (bType == CR_ENGINE_REALIZATION)
 | ||
|             {
 | ||
|                 pbrush->SetEngineRealization();
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 pbrush->SetDriverRealization();
 | ||
|             }
 | ||
|             pbrush->crBack(pebo->crCurrentBack());
 | ||
|             pbrush->ulPalTime(pebo->ulDCPalTime());
 | ||
|             pbrush->ulSurfTime(pebo->ulSurfPalTime());
 | ||
|             pbrush->ulRealization((ULONG_PTR)prbrush);
 | ||
|             pbrush->hdevRealization(pebo->psoTarg()->hdev());
 | ||
|             pbrush->crPalColor(pebo->crDCPalColor());
 | ||
| 
 | ||
|         // This must be set last, because once it's set, other selections of
 | ||
|         // this logical brush will attempt to use the cached brush. The use of
 | ||
|         // InterlockedExchange in this method enforces this
 | ||
| 
 | ||
|             pbrush->crForeLocked(pebo->crCurrentText());
 | ||
| 
 | ||
|         // The realization is now cached in the logical brush
 | ||
| 
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /******************************Public*Routine******************************\
 | ||
| * BRUSHOBJ_pvGetRbrush
 | ||
| *
 | ||
| * Returns a pointer to the driver's realization of the brush.
 | ||
| *
 | ||
| * History:
 | ||
| *  31-Oct-1993 -by- Michael Abrash
 | ||
| * Rewrote to cache the first realization in the logical brush.
 | ||
| *
 | ||
| *  8-Sep-1992 -by- Paul Butzi
 | ||
| * Rewrote it.
 | ||
| *
 | ||
| *  Wed 05-Jun-1991 -by- Patrick Haluptzok [patrickh]
 | ||
| * major revision
 | ||
| *
 | ||
| *  25-Apr-1991 -by- Patrick Haluptzok patrickh
 | ||
| * Wrote it.
 | ||
| \**************************************************************************/
 | ||
| 
 | ||
| PVOID
 | ||
| BRUSHOBJ_pvGetRbrush(
 | ||
|     BRUSHOBJ *pbo
 | ||
|     )
 | ||
| {
 | ||
|     EBRUSHOBJ *pebo = (EBRUSHOBJ *) pbo;
 | ||
| 
 | ||
|     ASSERTGDI(pbo->iSolidColor == 0xFFFFFFFF, "ERROR GDI iSolidColor");
 | ||
| 
 | ||
|     //
 | ||
|     // Check if the brush has already been realized.
 | ||
|     //
 | ||
| 
 | ||
|     if (pebo->pvRbrush != NULL)
 | ||
|     {
 | ||
|         return(pebo->pvRbrush);
 | ||
|     }
 | ||
| 
 | ||
|     //
 | ||
|     // Get this thing realized.
 | ||
|     //
 | ||
| 
 | ||
|     PDEVOBJ pdo(pebo->psoTarg()->hdev());
 | ||
| 
 | ||
|     if (!bGetRealizedBrush(pebo->pbrush(), pebo, PPFNDRV(pdo, RealizeBrush)))
 | ||
|     {
 | ||
|         if (pebo->pvRbrush != NULL)
 | ||
|         {
 | ||
|             VFREEMEM(DBRUSHSTART(pebo->pvRbrush));  // free the DBRUSH
 | ||
|             pebo->pvRbrush = NULL; // mark that there's no realization
 | ||
|         }
 | ||
| 
 | ||
|         return(NULL);
 | ||
|     }
 | ||
| 
 | ||
|     //
 | ||
|     // Try to cache the realization in the logical brush
 | ||
|     //
 | ||
| 
 | ||
|     vTryToCacheRealization(pebo,
 | ||
|                            (PDBRUSH) DBRUSHSTART(pebo->pvRbrush),
 | ||
|                            pebo->pbrush(),
 | ||
|                            CR_DRIVER_REALIZATION);
 | ||
| 
 | ||
|     return pebo->pvRbrush;
 | ||
| }
 | ||
| 
 | ||
| //
 | ||
| // User mode printer driver support
 | ||
| //
 | ||
| 
 | ||
| PVOID
 | ||
| BRUSHOBJ_pvGetRbrushUMPD(
 | ||
|     BRUSHOBJ *pbo
 | ||
|     )
 | ||
| 
 | ||
| {
 | ||
|     EBRUSHOBJ *pebo = (EBRUSHOBJ *) pbo;
 | ||
| 
 | ||
|     if (pbo->iSolidColor != 0xFFFFFFFF)
 | ||
|     {
 | ||
|         RIP("BRUSHOBJ_pvGetRbrush called for solid brush\n");
 | ||
|         return NULL;
 | ||
|     }
 | ||
| 
 | ||
|     //
 | ||
|     // Check if the brush has already been realized
 | ||
|     //
 | ||
| 
 | ||
|     if (pebo->pvRbrush != NULL)
 | ||
|         return pebo->pvRbrush;
 | ||
| 
 | ||
|     //
 | ||
|     // Realize the brush
 | ||
|     //
 | ||
| 
 | ||
|     PDEVOBJ pdo(pebo->psoTarg()->hdev());
 | ||
| 
 | ||
|     if (!bGetRealizedBrush(pebo->pbrush(), pebo, PPFNDRV(pdo, RealizeBrush)))
 | ||
|     {
 | ||
|         if (pebo->pvRbrush != NULL)
 | ||
|         {
 | ||
|             EngFreeUserMem(DBRUSHSTART(pebo->pvRbrush));
 | ||
|             pebo->pvRbrush = NULL;
 | ||
|         }
 | ||
| 
 | ||
|         return NULL;
 | ||
|     }
 | ||
| 
 | ||
| #if defined(_WIN64)
 | ||
|     //
 | ||
|     // if we are doing WOW64 printing, skip the caching.
 | ||
|     //
 | ||
| 
 | ||
|     PW32THREAD pThread = W32GetCurrentThread();
 | ||
|     
 | ||
|     if (pThread->pClientID == NULL)
 | ||
| #endif
 | ||
|     {
 | ||
|         // Try to cache the realization in the logical brush
 | ||
|     
 | ||
|         vTryToCacheRealization(pebo, (PDBRUSH)DBRUSHSTART(pebo->pvRbrush),
 | ||
|                 pebo->pbrush(), CR_DRIVER_REALIZATION);
 | ||
|     }
 | ||
| 
 | ||
|     return pebo->pvRbrush;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /******************************Public*Routine******************************\
 | ||
| * BRUSHOBJ_ulGetBrushColor
 | ||
| *
 | ||
| * Returns the RGB color for a solid brush.
 | ||
| *
 | ||
| *  Oct-18-1995 -by- Lingyun Wang
 | ||
| * Wrote it.
 | ||
| \**************************************************************************/
 | ||
| ULONG
 | ||
| BRUSHOBJ_ulGetBrushColor(
 | ||
|     BRUSHOBJ *pbo
 | ||
|     )
 | ||
| {
 | ||
|     EBRUSHOBJ *pebo = (EBRUSHOBJ *) pbo;
 | ||
| 
 | ||
|     if (pebo->bIsSolid())
 | ||
|     {
 | ||
|         if(pebo->flColorType & BR_ORIGCOLOR)
 | ||
|         {
 | ||
|             pebo->flColorType &= ~BR_ORIGCOLOR;
 | ||
|             return ((ULONG)(pebo->crOrignal()));
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             return ((ULONG)(pebo->crRealized()));
 | ||
|         }
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|         return (ULONG)(-1);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /******************************Public*Routine******************************\
 | ||
| * BRUSHOBJ_hGetColorTransform
 | ||
| *
 | ||
| * Retuens the color transform for a brush.
 | ||
| *
 | ||
| *  Feb-14-1997 -by- Hideyuki Nagase
 | ||
| * Wrote it.
 | ||
| ***************************************************************************/
 | ||
| 
 | ||
| HANDLE
 | ||
| BRUSHOBJ_hGetColorTransform(
 | ||
|     BRUSHOBJ *pbo
 | ||
|     )
 | ||
| {
 | ||
|     ICMAPI(("BRUSHOBJ_hGetColorTransform()\n"));
 | ||
| 
 | ||
|     if (pbo == NULL)
 | ||
|     {
 | ||
|         WARNING("BRUSHOBJ_hGetColorTransform() BRUSHOBJ is NULL\n");
 | ||
|         return(NULL);
 | ||
|     }
 | ||
| 
 | ||
|     EBRUSHOBJ *pebo = (EBRUSHOBJ *) pbo;
 | ||
| 
 | ||
|     //
 | ||
|     // if ICM is not enabled for this. Or if ICM is done by host,
 | ||
|     // Color transform handle is for host ICM it is no meanings
 | ||
|     // for device driver. then just return NULL.
 | ||
|     //
 | ||
|     if (pebo->bIsDeviceICM())
 | ||
|     {
 | ||
|         if (pebo->hcmXform())
 | ||
|         {
 | ||
|             COLORTRANSFORMOBJ CXFormObj(pebo->hcmXform());
 | ||
| 
 | ||
|             if (CXFormObj.bValid())
 | ||
|             {
 | ||
|                 return(CXFormObj.hGetDeviceColorTransform());
 | ||
|             }
 | ||
| 
 | ||
|             ICMMSG(("BRUSHOBJ_hGetColorTransform() COLORTRANSFORMOBJ is invalid\n"));
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             ICMMSG(("BRUSHOBJ_hGetColorTransform() Ident. color transform\n"));
 | ||
|         }
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|         ICMMSG(("BRUSHOBJ_hGetColorTransform() ICM on device is not enabled\n"));
 | ||
|     }
 | ||
| 
 | ||
|     return(NULL);
 | ||
| }
 | ||
| 
 | ||
| /******************************Public*Routine******************************\
 | ||
| * pvGetEngRbrush
 | ||
| *
 | ||
| * Returns:  A pointer to the engines's realization of a logical brush.
 | ||
| *
 | ||
| * Only the engine calls this, it is not exported.
 | ||
| *
 | ||
| * History:
 | ||
| *  31-Oct-1993 -by- Michael Abrash
 | ||
| * Rewrote to cache the first realization in the logical brush.
 | ||
| *
 | ||
| *  8-Sep-1992 -by- Paul Butzi
 | ||
| * Rewrote it.
 | ||
| *
 | ||
| *  Wed 05-Jun-1991 -by- Patrick Haluptzok [patrickh]
 | ||
| * major revision
 | ||
| *
 | ||
| *  25-Apr-1991 -by- Patrick Haluptzok patrickh
 | ||
| * Wrote it - First pass.
 | ||
| \**************************************************************************/
 | ||
| 
 | ||
| PVOID
 | ||
| pvGetEngRbrush(
 | ||
|     BRUSHOBJ *pbo
 | ||
|     )
 | ||
| {
 | ||
|     EBRUSHOBJ *pebo = (EBRUSHOBJ *) pbo;
 | ||
| 
 | ||
|     ASSERTGDI(pbo->iSolidColor == 0xFFFFFFFF, "ERROR GDI iSolidColor");
 | ||
| 
 | ||
| // Check if the brush has already been realized.
 | ||
| 
 | ||
|     if (pebo->pengbrush() != (PVOID) NULL)
 | ||
|     {
 | ||
|         return pebo->pengbrush();
 | ||
|     }
 | ||
| 
 | ||
| // Get this thing realized.
 | ||
| 
 | ||
|     PDEVOBJ pdo(pebo->psoTarg()->hdev());
 | ||
| 
 | ||
|     if (!bGetRealizedBrush(pebo->pbrush(), pebo, EngRealizeBrush))
 | ||
|     {
 | ||
|         if (pebo->pengbrush() != NULL)
 | ||
|         {
 | ||
|             VFREEMEM(pebo->pengbrush());  // free the DBRUSH
 | ||
|             pebo->pengbrush(NULL);  // mark that there's no realization
 | ||
|         }
 | ||
| 
 | ||
|         return(NULL);
 | ||
|     }
 | ||
| 
 | ||
| // Try to cache the realization in the logical brush
 | ||
| 
 | ||
|     vTryToCacheRealization(pebo, pebo->pengbrush(), pebo->pbrush(),
 | ||
|             CR_ENGINE_REALIZATION);
 | ||
| 
 | ||
|     return(pebo->pengbrush());
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /******************************Public*Routine******************************\
 | ||
| * bGetRealizedBrush
 | ||
| *
 | ||
| * Returns: Pointer to a Realized brush.
 | ||
| *
 | ||
| * NOTE: The surface in pebo->psoTarg() is the surface of the original
 | ||
| *       destination of the drawing call.  If a display driver was called,
 | ||
| *       but it punts by calling back to the engine with an engine-managed
 | ||
| *       bitmap it created, psoTarg() will still point to the original
 | ||
| *       display surface, not the DIB surface.  The surface will have the
 | ||
| *       same hdev, iFormat, etc., but this means that the iType will be
 | ||
| *       wrong, so don't reference it!  (EngRealizeBrush actually accounts
 | ||
| *       for this little lie.)
 | ||
| *
 | ||
| * History:
 | ||
| *  14-Jul-1992 -by-  Eric Kutter [erick]
 | ||
| *   added exception handling, changed from VOID to BOOL
 | ||
| *
 | ||
| *  Mon 07-Oct-1991 -by- Patrick Haluptzok [patrickh]
 | ||
| * add support for DIB_PAL_COLORS flag.
 | ||
| *
 | ||
| *  04-Jun-1991 -by- Patrick Haluptzok patrickh
 | ||
| * Wrote it.
 | ||
| \**************************************************************************/
 | ||
| 
 | ||
| BOOL
 | ||
| bGetRealizedBrush(
 | ||
|     BRUSH *pbrush,
 | ||
|     EBRUSHOBJ *pebo,
 | ||
|     PFN_DrvRealizeBrush pfnDrv
 | ||
|     )
 | ||
| {
 | ||
|     ASSERTGDI(pebo->iSolidColor == 0xFFFFFFFF, "ERROR GDI iSolidColor");
 | ||
|     ASSERTGDI(pfnDrv != (PFN_DrvRealizeBrush) 0, "ERROR pfnDrv");
 | ||
| 
 | ||
|     //
 | ||
|     // quick out if it is a NULL brush
 | ||
|     //
 | ||
| 
 | ||
|     if (pbrush->ulStyle() == HS_NULL)
 | ||
|     {
 | ||
|         WARNING1("You are doing output calls with a NULL brush\n");
 | ||
|         return(FALSE);
 | ||
|     }
 | ||
| 
 | ||
|     //
 | ||
|     // Dispatch off to driver to get brush realized.
 | ||
|     //
 | ||
| 
 | ||
|     ULONG       ulStyle = pbrush->ulStyle();
 | ||
|     SURFOBJ    *psoPattern;
 | ||
|     SURFOBJ    *psoMask = NULL;
 | ||
|     XEPALOBJ    palSrc;
 | ||
|     XEPALOBJ    palDest;
 | ||
|     SURFREF     SurfBmoPattern;
 | ||
|     EXLATEOBJ   exlo;
 | ||
|     XLATE      *pxlo = NULL;
 | ||
|     SURFMEM     SurfDimo;
 | ||
| 
 | ||
|     //
 | ||
|     // We default to this.
 | ||
|     //
 | ||
| 
 | ||
|     PDEVOBJ po(pebo->psoTarg()->hdev());
 | ||
|     ASSERTGDI(po.bValid(), "ERROR BRUSHOBJ_ 5");
 | ||
| 
 | ||
|     //
 | ||
|     // We need to hold the Devlock to protect against dynamic mode changes
 | ||
|     // while we muck around in the driver.  If we're being call by the
 | ||
|     // driver, we're guaranteed to already be holding it, so we only have
 | ||
|     // to do this if we're being called by GDI's Eng functions.
 | ||
|     //
 | ||
| 
 | ||
|     DEVLOCKOBJ dlo;
 | ||
|     if (pfnDrv == EngRealizeBrush)
 | ||
|     {
 | ||
|         dlo.vLock(po);
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|         dlo.vInit();
 | ||
|     }
 | ||
| 
 | ||
|     if (pbrush->ulStyle() < HS_DDI_MAX)
 | ||
|     {
 | ||
|         //
 | ||
|         // For hatch brushes, the pattern is also the mask
 | ||
|         //
 | ||
| 
 | ||
|         SurfBmoPattern.vAltLock((HSURF)po.hbmPattern(pbrush->ulStyle()));
 | ||
|         psoMask = SurfBmoPattern.pSurfobj();
 | ||
| 
 | ||
|         if (exlo.pCreateXlateObject(2))
 | ||
|         {
 | ||
|             ULONG ulValue1, ulValue2;
 | ||
| 
 | ||
|             if (pebo->bIsCMYKColor())
 | ||
|             {
 | ||
|                 //
 | ||
|                 // We are in CMYK color context, we just set CMYK color
 | ||
|                 //
 | ||
|                 ulValue1 = pebo->crCurrentBack();
 | ||
|                 ulValue2 = pebo->crRealized();
 | ||
| 
 | ||
|                 exlo.pxlo()->vSetIndex(0, ulValue1);
 | ||
|                 exlo.pxlo()->vSetIndex(1, ulValue2);
 | ||
| 
 | ||
|                 pxlo = exlo.pxlo();
 | ||
|                 pxlo->vCheckForICM(pebo->hcmXform(),pebo->lIcmMode());
 | ||
|                 pxlo->ppalSrc = ppalMono;
 | ||
|                 pxlo->ppalDst = pebo->palSurf().ppalGet();
 | ||
|                 pxlo->ppalDstDC = pebo->palDC().ppalGet();
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 ulValue1 = ulGetNearestIndexFromColorref(
 | ||
|                                     pebo->palSurf(),
 | ||
|                                     pebo->palDC(),
 | ||
|                                     pebo->crCurrentBack()
 | ||
|                                     );
 | ||
| 
 | ||
|                 ulValue2 = ulGetNearestIndexFromColorref(
 | ||
|                                     pebo->palSurf(),
 | ||
|                                     pebo->palDC(),
 | ||
|                                     pebo->crRealized()
 | ||
|                                     );
 | ||
| 
 | ||
|                 //
 | ||
|                 // Windows compability issue:
 | ||
|                 // force to draw on the background
 | ||
|                 //
 | ||
|                 // We force the forground to be mapped
 | ||
|                 // to an index opposite to the background
 | ||
|                 //
 | ||
| 
 | ||
|                 if ((pebo->psoTarg()->iFormat() == BMF_1BPP) &&
 | ||
|                     (pebo->palSurf().bIsIndexed()) &&
 | ||
|                     (pebo->crCurrentBack() !=  pebo->crRealized()) &&
 | ||
|                     (ulValue1 == ulValue2))
 | ||
|                 {
 | ||
|                      ulValue2 = 1-ulValue1;
 | ||
|                 }
 | ||
| 
 | ||
|                 exlo.pxlo()->vSetIndex(0, ulValue1);
 | ||
|                 exlo.pxlo()->vSetIndex(1, ulValue2);
 | ||
| 
 | ||
|                 pxlo = exlo.pxlo();
 | ||
|                 pxlo->vCheckForICM(pebo->hcmXform(),pebo->lIcmMode());
 | ||
|                 pxlo->vCheckForTrivial();
 | ||
|                 pxlo->ppalSrc = ppalMono;
 | ||
|                 pxlo->ppalDst = pebo->palSurf().ppalGet();
 | ||
|                 pxlo->ppalDstDC = pebo->palDC().ppalGet();
 | ||
|             }
 | ||
|             pxlo->iForeDst = ulValue1;
 | ||
|             pxlo->iBackDst = ulValue2;
 | ||
|             pxlo->flPrivate |= XLATE_FROM_MONO;
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             WARNING("ERROR failed to create hatch xlate\n");
 | ||
|             return(FALSE);
 | ||
|         }
 | ||
|     }
 | ||
|     else if (pbrush->ulStyle() < HS_NULL)
 | ||
|     {
 | ||
|         //
 | ||
|         // For solid brushes.
 | ||
|         //
 | ||
| 
 | ||
|         ASSERTGDI(pbrush->flAttrs() & BR_IS_SOLID, "ERROR non-solid brush");
 | ||
|         ASSERTGDI((pbrush->flAttrs() & BR_DITHER_OK) ||
 | ||
|                   (po.bCapsForceDither()),
 | ||
|                   "ERROR BRUSHOBJ_ 1");
 | ||
| 
 | ||
|         //
 | ||
|         // We will not dither CMYK color brush. Driver should not call BRUSHOBJ_pvGetRbrush 
 | ||
|         // with CMYK solid color brush.
 | ||
|         //
 | ||
| 
 | ||
|         if (pebo->bIsCMYKColor())
 | ||
|         {
 | ||
|             WARNING("ERROR bGetRealizedBrush() Can't dither CMYK color brush\n");
 | ||
|             return (FALSE);
 | ||
|         }
 | ||
| 
 | ||
|         //
 | ||
|         // This means they want us to dither the color and nothing
 | ||
|         // in their palette is close enough that we can't just use
 | ||
|         // a solid color.
 | ||
|         //
 | ||
| 
 | ||
|         if (pebo->crRealized() & 0x01000000)
 | ||
|         {
 | ||
|             pebo->crRealized(rgbFromColorref(pebo->palSurf(),
 | ||
|                                              pebo->palDC(),
 | ||
|                                              pebo->crRealized()));
 | ||
|         }
 | ||
| 
 | ||
|         //
 | ||
|         // Use the nifty DitherOnRealize option, if the driver supports it and
 | ||
|         // we're not realizing the brush on behalf of the engine simulations
 | ||
|         // (since the engine will be drawing, it will need its own realization,
 | ||
|         // not the driver's):
 | ||
|         //
 | ||
| 
 | ||
|         if ((po.flGraphicsCaps() & GCAPS_DITHERONREALIZE) &&
 | ||
|             (pfnDrv != EngRealizeBrush))
 | ||
|         {
 | ||
|             if ((*pfnDrv) (pebo,
 | ||
|                            pebo->psoTarg()->pSurfobj(),
 | ||
|                            (SURFOBJ *) NULL,
 | ||
|                            (SURFOBJ *) NULL,
 | ||
|                            NULL,
 | ||
|                            pebo->crRealized() | RB_DITHERCOLOR))
 | ||
|             {
 | ||
|                 return(TRUE);
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         DEVBITMAPINFO dbmi;
 | ||
| 
 | ||
|         if (pebo->psoTarg()->iFormat() == BMF_1BPP)
 | ||
|         {
 | ||
|             dbmi.iFormat = BMF_1BPP;
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             dbmi.iFormat = po.iDitherFormat();
 | ||
|         }
 | ||
| 
 | ||
|         dbmi.cxBitmap = po.cxDither();
 | ||
|         dbmi.cyBitmap = po.cyDither();
 | ||
|         dbmi.hpal = 0;
 | ||
|         dbmi.fl = BMF_TOPDOWN;
 | ||
| 
 | ||
|         if (!SurfDimo.bCreateDIB(&dbmi, NULL))
 | ||
|         {
 | ||
|             WARNING("Failed memory alloc in dither brush\n");
 | ||
|             return(FALSE);
 | ||
|         }
 | ||
| 
 | ||
|         ULONG iRes;
 | ||
|         ULONG iDitherMode = ((pebo->psoTarg()->iFormat() == BMF_1BPP) ? DM_MONOCHROME: DM_DEFAULT);
 | ||
| 
 | ||
|         if (PPFNVALID(po, DitherColor))
 | ||
|         {
 | ||
|             iRes = (*PPFNDRV(po, DitherColor)) (
 | ||
|                    po.bUMPD() ? (DHPDEV)po.ppdev : po.dhpdev(),
 | ||
|                    iDitherMode,
 | ||
|                    pebo->crRealized(),
 | ||
|                    (PULONG) SurfDimo.ps->pvBits());
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             iRes = EngDitherColor(po.hdev(),
 | ||
|                                   iDitherMode,
 | ||
|                                   pebo->crRealized(),
 | ||
|                                   (PULONG) SurfDimo.ps->pvBits());
 | ||
|         }
 | ||
| 
 | ||
|         switch (iRes)
 | ||
|         {
 | ||
|         case DCR_DRIVER:
 | ||
|             pxlo = &xloIdent;
 | ||
|             break;
 | ||
| 
 | ||
|         case DCR_HALFTONE:
 | ||
|         {
 | ||
|             if ((po.pDevHTInfo() == NULL) && !po.bEnableHalftone(NULL))
 | ||
|                 return(FALSE);
 | ||
| 
 | ||
|             DEVICEHALFTONEINFO *pDevHTInfo = (DEVICEHALFTONEINFO *)po.pDevHTInfo();
 | ||
| 
 | ||
|             COLORTRIAD ColorTriad;
 | ||
|             CHBINFO    CHBInfo;
 | ||
|             COLORREF   cr = pebo->crRealized();
 | ||
| 
 | ||
|             ColorTriad.Type              = COLOR_TYPE_RGB;
 | ||
|             ColorTriad.BytesPerPrimary   = sizeof(BYTE);
 | ||
|             ColorTriad.BytesPerEntry     = sizeof(DWORD);
 | ||
|             ColorTriad.PrimaryOrder      = PRIMARY_ORDER_RGB;
 | ||
|             ColorTriad.PrimaryValueMax   = 255;
 | ||
|             ColorTriad.ColorTableEntries = 1;
 | ||
|             ColorTriad.pColorTable       = (LPVOID)&cr;
 | ||
| 
 | ||
|             CHBInfo.Flags = (BYTE)((po.GdiInfo()->flHTFlags & HT_FLAG_OUTPUT_CMY) ?
 | ||
|                                                         0 : CHBF_USE_ADDITIVE_PRIMS);
 | ||
| 
 | ||
|         // Control ICM bits for halftoning
 | ||
| 
 | ||
|             if ((pebo->bIsAppsICM()) ||
 | ||
|                 (!pebo->bDeviceCalibrate() && (pebo->bIsHostICM() || pebo->bIsDeviceICM())))
 | ||
|             {
 | ||
|                 ICMDUMP(("bGetRealizedBrush(): ICM with Halftone (Dynamic Bit On)\n"));
 | ||
| 
 | ||
|                 // Some kind of ICM (ICM on Application, Graphics Engine or Device)
 | ||
|                 // is enabled, so tell halftoning code to disable thier color adjustment.
 | ||
| 
 | ||
|                 CHBInfo.Flags |= CHBF_ICM_ON;
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 ICMDUMP(("bGetRealizedBrush(): ICM with Halftone (Dynamic Bit Off)\n"));
 | ||
|             }
 | ||
| 
 | ||
|             if ((pDevHTInfo->cxPattern != dbmi.cxBitmap) ||
 | ||
|                 (pDevHTInfo->cyPattern != dbmi.cyBitmap))
 | ||
|             {
 | ||
|                 SurfDimo.ps->bDeleteSurface();
 | ||
|                 dbmi.cxBitmap = pDevHTInfo->cxPattern;
 | ||
|                 dbmi.cyBitmap = pDevHTInfo->cyPattern;
 | ||
| 
 | ||
|                 if (!SurfDimo.bCreateDIB(&dbmi, NULL))
 | ||
|                 {
 | ||
|                     WARNING("Failed memory alloc in dither brush1\n");
 | ||
|                     return(FALSE);
 | ||
|                 }
 | ||
|             }
 | ||
| 
 | ||
|             switch(po.GdiInfo()->ulHTOutputFormat)
 | ||
|             {
 | ||
|             case HT_FORMAT_1BPP:
 | ||
|                 CHBInfo.DestSurfaceFormat = (BYTE)BMF_1BPP;
 | ||
|                 break;
 | ||
|             case HT_FORMAT_4BPP:
 | ||
|                 CHBInfo.DestSurfaceFormat = (BYTE)BMF_4BPP;
 | ||
|                 break;
 | ||
|             case HT_FORMAT_4BPP_IRGB:
 | ||
|                 CHBInfo.DestSurfaceFormat = (BYTE)BMF_4BPP_VGA16;
 | ||
|                 break;
 | ||
|             case HT_FORMAT_8BPP:
 | ||
|                 CHBInfo.DestSurfaceFormat = (BYTE)BMF_8BPP_VGA256;
 | ||
|                 break;
 | ||
|             case HT_FORMAT_16BPP:
 | ||
|                 //
 | ||
|                 // Need to switch between BMF_16BPP_555 and BMF_16BPP_565
 | ||
|                 //
 | ||
|                 CHBInfo.DestSurfaceFormat = (BYTE)BMF_16BPP_555;
 | ||
|                 break;
 | ||
|             case HT_FORMAT_32BPP:
 | ||
|                 CHBInfo.DestSurfaceFormat = (BYTE)BMF_32BPP;
 | ||
|                 break;
 | ||
|             default:
 | ||
|                 WARNING("Halftone format not supported\n");
 | ||
|                 return(FALSE);
 | ||
|             }
 | ||
| 
 | ||
|             CHBInfo.DestScanLineAlignBytes = BMF_ALIGN_DWORD;
 | ||
|             CHBInfo.DestPrimaryOrder       = (BYTE)po.GdiInfo()->ulPrimaryOrder;
 | ||
| 
 | ||
|         // Brushes, unlike scanned in images, have linear RGB gamma.
 | ||
|         // Use a gamma value of 1 can produce lighter, closer to wfw halftone
 | ||
|         // images for solid brushes.  This is to fix powerpnt shaded background
 | ||
|         // printing.  Other apps that print black text on dark background will
 | ||
|         // benefit from this fix as well.
 | ||
| 
 | ||
|             COLORADJUSTMENT ca = *pebo->pColorAdjustment();
 | ||
|             ca.caRedGamma = 10000;
 | ||
|             ca.caGreenGamma = 10000;
 | ||
|             ca.caBlueGamma = 10000;
 | ||
| 
 | ||
|             if (HT_CreateHalftoneBrush(
 | ||
|                               pDevHTInfo,
 | ||
|                               (PHTCOLORADJUSTMENT)&ca,
 | ||
|                               &ColorTriad,
 | ||
|                               CHBInfo,
 | ||
|                               (PULONG)SurfDimo.ps->pvBits()) > 0)
 | ||
|             {
 | ||
|             // Set up the translate object.
 | ||
| 
 | ||
|                 if (po.bHTPalIsDevPal())
 | ||
|                 {
 | ||
|                     pxlo = &xloIdent;
 | ||
|                 }
 | ||
|                 else
 | ||
|                 {
 | ||
|                     EPALOBJ palHT((HPALETTE)pDevHTInfo->DeviceOwnData);
 | ||
| 
 | ||
|                     palDest.ppalSet(pebo->psoTarg()->ppal());
 | ||
| 
 | ||
|                     if (!exlo.bInitXlateObj(
 | ||
|                                     pebo->hcmXform(),
 | ||
|                                     pebo->lIcmMode(),
 | ||
|                                     palHT, palDest,
 | ||
|                                     pebo->palDC(),
 | ||
|                                     pebo->palDC(),
 | ||
|                                     pebo->crCurrentText(),
 | ||
|                                     pebo->crCurrentBack(),
 | ||
|                                     0x00FFFFFF
 | ||
|                                     ))
 | ||
|                     {
 | ||
|                         WARNING("Failed to create an xlate bGetRealizedBrush DIB_PAL_COLORS\n");
 | ||
|                         return(FALSE);
 | ||
|                     }
 | ||
| 
 | ||
|                     pxlo = exlo.pxlo();
 | ||
|                 }
 | ||
|                 break;
 | ||
|             }
 | ||
|         } // case DCR_HALFTONE
 | ||
| 
 | ||
|         default:
 | ||
|             WARNING("DrvDitherColor returned invalid value or failed\n");
 | ||
|             return(FALSE);
 | ||
|         } // switch (iRes)
 | ||
|     }
 | ||
|     else // if (pbrush->ulStyle() >= HS_NULL)
 | ||
|     {
 | ||
|         BOOL bIcmBrush = FALSE;
 | ||
| 
 | ||
|         //
 | ||
|         // For bitmap/pattern brushes.
 | ||
|         //
 | ||
| 
 | ||
|         HSURF hDIB = (HSURF)pbrush->hbmPattern();
 | ||
| 
 | ||
|         ASSERTGDI(pbrush->ulStyle() <= HS_PATMSK, "ERROR ulStyle is bad");
 | ||
| 
 | ||
|     // ICM is enabled ? and the Brush is DIB ? For Device Depend Bitmap, we will
 | ||
|     // not enable ICM. Only for DIB.
 | ||
| 
 | ||
|         if (pebo->bIsHostICM())
 | ||
|         {
 | ||
|             if (pebo->hcmXform() != NULL)
 | ||
|             {
 | ||
|                 if (pbrush->flAttrs() & BR_IS_DIB)
 | ||
|                 {
 | ||
|                 // if ICM is enabled, the BRUSHOBJ should have color transform.
 | ||
| 
 | ||
|                     if (pbrush->iUsage() == DIB_RGB_COLORS)
 | ||
|                     {
 | ||
|                         ICMMSG(("bGetRealizedBrush: TRY Find ICM DIB\n"));
 | ||
| 
 | ||
|                     // Find color translated brush DIB.
 | ||
| 
 | ||
|                         HSURF hIcmDIB = (HSURF)(pbrush->hFindIcmDIB(pebo->hcmXform()));
 | ||
| 
 | ||
|                         if (hIcmDIB == NULL)
 | ||
|                         {
 | ||
|                         // Somehow, we could not find DIB, just use orginal.
 | ||
| 
 | ||
|                             WARNING1("bGetRealizedBrush(): hFindIcmDIB() returns NULL\n");
 | ||
|                         }
 | ||
|                         else
 | ||
|                         {
 | ||
|                         // Replace DIB handle with ICM-ed DIB.
 | ||
| 
 | ||
|                             hDIB      = hIcmDIB;
 | ||
|                             bIcmBrush = TRUE;
 | ||
|                         }
 | ||
|                     }
 | ||
|                     else
 | ||
|                     {
 | ||
|                     // if DIB is other than DIB_RGB_COLORS, ICM DIB will not be used.
 | ||
| 
 | ||
|                         ICMMSG(("bGetRealizedBrush(): Brush color is not DIB_RGB_COLORS\n"));
 | ||
|                     }
 | ||
|                 }
 | ||
|                 else if (pbrush->flAttrs() & BR_IS_MONOCHROME)
 | ||
|                 {
 | ||
|                     ICMMSG(("bGetRealizedBrush(): Brush color is BR_IS_MONOCHROME\n"));
 | ||
| 
 | ||
|                     bIcmBrush = TRUE;
 | ||
|                 }
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|             // ICM is enabled, but no color transform, it means identical color transform
 | ||
|             // so, there is no ICM-ed DIB.
 | ||
| 
 | ||
|                 ICMMSG(("bGetRealizedBrush(): Color transform is identical\n"));
 | ||
|           
 | ||
|             // If we are in CMYK mode, we must have color transform.
 | ||
| 
 | ||
|                 if (!pebo->bIsCMYKColor())
 | ||
|                 {
 | ||
|                     bIcmBrush = TRUE;
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|         else if (pebo->bIsAppsICM() || pebo->bIsDeviceICM())
 | ||
|         {
 | ||
|             bIcmBrush = TRUE;
 | ||
|         }
 | ||
| 
 | ||
|         SurfBmoPattern.vAltLock(hDIB);
 | ||
| 
 | ||
|         if(!SurfBmoPattern.bValid())
 | ||
|         {
 | ||
|             WARNING("WARNING:bGetRealizedBrush(): Invalid SurfBmopattern\n");
 | ||
|             return(FALSE);
 | ||
|         }           
 | ||
| 
 | ||
|         palSrc.ppalSet(SurfBmoPattern.ps->ppal());
 | ||
|         palDest.ppalSet(pebo->psoTarg()->ppal());
 | ||
| 
 | ||
|         if (pbrush->bPalColors())
 | ||
|         {
 | ||
|             ASSERTGDI(palSrc.bValid(), "ERROR3invalid hpal pvGetEngRbrush\n");
 | ||
| 
 | ||
|             if (!exlo.bMakeXlate((PUSHORT) palSrc.apalColorGet(),
 | ||
|                                  pebo->palDC(),
 | ||
|                                  pebo->psoTarg(),
 | ||
|                                  palSrc.cColorTableLength(),
 | ||
|                                  palSrc.cEntries()))
 | ||
|             {
 | ||
|                 WARNING("Failed to create an xlate bGetRealizedBrush DIB_PAL_COLORS\n");
 | ||
|                 return(FALSE);
 | ||
|             }
 | ||
| 
 | ||
|             pxlo = exlo.pxlo();
 | ||
|         }
 | ||
|         else if (pbrush->bPalIndices())
 | ||
|         {
 | ||
|             if (SurfBmoPattern.ps->iFormat() != pebo->psoTarg()->iFormat())
 | ||
|             {
 | ||
|                 WARNING("Output failed: DIB_PAL_INDICES brush not compatible with dest surface\n");
 | ||
|                 return(FALSE);
 | ||
|             }
 | ||
| 
 | ||
|             pxlo = &xloIdent;
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|         // With our wonderful API we can't fail a brush selection like Windows would.
 | ||
|         // Instead we let the app think he selected the bitmap brush in and then at
 | ||
|         // realize time if that wasn't a valid selection we fail the realize.  Good
 | ||
|         // luck writing new apps.
 | ||
| 
 | ||
|             PPALETTE ppalSrcTmp;
 | ||
| 
 | ||
|         // We need to make sure this could be selected into this DC.  If it is a device
 | ||
|         // managed bitmap, it must be the same device.
 | ||
| 
 | ||
|             if ((
 | ||
|                  (SurfBmoPattern.ps->iType() != STYPE_BITMAP) ||
 | ||
|                  (SurfBmoPattern.ps->dhsurf() != 0)
 | ||
|                 )
 | ||
|                  &&
 | ||
|                 (SurfBmoPattern.ps->hdev() != po.hdev()))
 | ||
|             {
 | ||
|                 WARNING1("bGetRealizedBrush failed Device surface for another PDEV\n");
 | ||
|                 return (FALSE);
 | ||
|             }
 | ||
|             else if (SurfBmoPattern.ps->ppal() != NULL)
 | ||
|             {
 | ||
|             // No problem, we already have color information.
 | ||
| 
 | ||
|                 ppalSrcTmp = SurfBmoPattern.ps->ppal();
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 if (SurfBmoPattern.ps->iFormat() == po.iDitherFormat())
 | ||
|                 {
 | ||
|                     if (po.bIsPalManaged())
 | ||
|                     {
 | ||
|                         ppalSrcTmp = (PPALETTE) NULL;
 | ||
|                     }
 | ||
|                     else
 | ||
|                     {
 | ||
|                         ppalSrcTmp = po.ppalSurf();
 | ||
|                     }
 | ||
|                 }
 | ||
|                 else if (SurfBmoPattern.ps->iFormat() == pebo->iMetaFormat())
 | ||
|                 {
 | ||
|                 // We can try to use palette from meta.
 | ||
| 
 | ||
|                     ppalSrcTmp = pebo->palMeta().ppalGet();
 | ||
|                 }
 | ||
|                 else if (SurfBmoPattern.ps->iFormat() == BMF_8BPP)
 | ||
|                 {
 | ||
|                     if (po.bIsPalManaged())
 | ||
|                     {
 | ||
|                         ppalSrcTmp = (PPALETTE) NULL;
 | ||
|                     }
 | ||
|                     else
 | ||
|                     {
 | ||
|                         ppalSrcTmp = ppalDefaultSurface8bpp;
 | ||
|                     }
 | ||
|                 }
 | ||
|                 else 
 | ||
|                 {
 | ||
|                     if (po.bMetaDriver())
 | ||
|                         ppalSrcTmp = (PPALETTE) NULL;
 | ||
|                     else
 | ||
|                     {
 | ||
|                         WARNING("bGetRealizedBrush failed - bitmap not compatible with surface\n");
 | ||
|                         return FALSE;
 | ||
|                     }
 | ||
|                 }
 | ||
|             }
 | ||
| 
 | ||
|             // Replace source palette with proper one which decided in above.
 | ||
| 
 | ||
|             palSrc.ppalSet(ppalSrcTmp);
 | ||
| 
 | ||
|             if (!exlo.bInitXlateObj(
 | ||
|                             (bIcmBrush ? pebo->hcmXform() : NULL),
 | ||
|                             (bIcmBrush ? pebo->lIcmMode() : DC_ICM_OFF),
 | ||
|                             palSrc,
 | ||
|                             palDest,
 | ||
|                             pebo->palDC(),
 | ||
|                             pebo->palDC(),
 | ||
|                             pebo->crCurrentText(),
 | ||
|                             pebo->crCurrentBack(),
 | ||
|                             0x00FFFFFF
 | ||
|                             ))
 | ||
|             {
 | ||
|                 WARNING("Failed to create an xlate pvGetRbrush\n");
 | ||
|                 return (FALSE);
 | ||
|             }
 | ||
| 
 | ||
|             pxlo = exlo.pxlo();
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
| // Do the right thing if a pattern is provided
 | ||
| 
 | ||
|     if (SurfBmoPattern.bValid())
 | ||
|     {
 | ||
|         psoPattern = SurfBmoPattern.pSurfobj();
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|     // Check for dithering
 | ||
| 
 | ||
|         if (SurfDimo.bValid())
 | ||
|         {
 | ||
|             psoPattern = SurfDimo.pSurfobj();
 | ||
|         }
 | ||
|         else
 | ||
|             psoPattern = (SURFOBJ *) NULL;
 | ||
|     }
 | ||
| 
 | ||
| // Call off to driver to the RealizeBrush
 | ||
| 
 | ||
|     return((*pfnDrv) (pebo, pebo->psoTarg()->pSurfobj(),
 | ||
|                     psoPattern, psoMask,
 | ||
|                     pxlo,
 | ||
|                     ulStyle));
 | ||
| }
 |