Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1191 lines
36 KiB

/******************************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
//
//Make sure the brush is indeed realized
if (pebo->pvRbrush == NULL)
return(NULL);
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;
}
//Make sure the brush is indeed realized
if (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));
}