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.
 
 
 
 
 
 

1130 lines
29 KiB

/******************************Module*Header*******************************\
* Module Name: brushapi.cxx *
* *
* Contains all the various GDI versions of Brush creation. *
* *
* Created: 06-Nov-1990 14:46:03 *
* Author: Walt Moore [waltm] *
* *
* Copyright (c) 1990-1999 Microsoft Corporation *
\**************************************************************************/
#include "precomp.hxx"
#include "engline.hxx"
// Default wide-line style arrays:
ULONG gaulGeometricDot[] = { 1, 1 };
ULONG gaulGeometricDash[] = { 3, 1 };
ULONG gaulGeometricDashDot[] = { 3, 1, 1, 1 };
ULONG gaulGeometricDashDotDot[] = { 3, 1, 1, 1, 1, 1 };
// Default cosmetic style arrays (must all sum to 8):
LONG_FLOAT galeCosmeticDot[] = { {1}, {1}, {1}, {1},
{1}, {1}, {1}, {1} };
LONG_FLOAT galeCosmeticDash[] = { {6}, {2} };
LONG_FLOAT galeCosmeticDashDot[] = { {3}, {2}, {1}, {2} };
LONG_FLOAT galeCosmeticDashDotDot[] = { {3}, {1}, {1}, {1}, {1}, {1} };
/**************************************************************************\
* hCreateSolidBrushInternal(clrr, bPen)
*
* Creates a solid brush. Whether or not the brush is solid or dithered
* will depend on what mode the DC is in at realization time.
*
\**************************************************************************/
HBRUSH
hCreateSolidBrushInternal(
COLORREF clrr,
BOOL bPen,
HBRUSH hbr,
BOOL bSharedMem)
{
HBRUSH hbrReturn = NULL;
if (hbr)
{
//
// If an already created brush is passed, just try to set it.
//
if (GreSetSolidBrushInternal(hbr,clrr,bPen,FALSE))
{
hbrReturn = hbr;
}
}
else
{
BRUSHMEMOBJ brmo(clrr, HS_DITHEREDCLR, bPen, bSharedMem);
if (brmo.bValid())
{
brmo.vKeepIt();
brmo.vEnableDither();
hbrReturn = brmo.hbrush();
}
}
return hbrReturn;
}
/**************************************************************************\
* GreCreateSolidBrush()
*
\**************************************************************************/
HBRUSH
GreCreateSolidBrush(
COLORREF clrr)
{
return(hCreateSolidBrushInternal(clrr,FALSE,NULL,FALSE));
}
/**************************************************************************\
* NtGdiCreateSolidBrush()
*
\**************************************************************************/
HBRUSH
APIENTRY
NtGdiCreateSolidBrush(
COLORREF cr,
HBRUSH hbr
)
{
HBRUSH hbrush;
hbrush = hCreateSolidBrushInternal(cr, FALSE, hbr, TRUE);
return (hbrush);
}
/**************************************************************************\
* hCreateHatchBrushInternal(ulStyle, clrr, bPen)
*
* Creates a hatch brush.
*
* History:
* 07-Jun-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
HBRUSH
hCreateHatchBrushInternal(
ULONG ulStyle,
COLORREF clrr,
BOOL bPen)
{
HBRUSH hbr = NULL;
if (ulStyle <= HS_API_MAX-1)
{
BRUSHMEMOBJ brmo(clrr, ulStyle, bPen, FALSE);
if (brmo.bValid())
{
brmo.vKeepIt();
hbr = brmo.hbrush();
}
}
return hbr;
}
/**************************************************************************\
* NtGdiCreateHatchBrushInternal(ulStyle, clrr, bPen)
*
\**************************************************************************/
HBRUSH
APIENTRY
NtGdiCreateHatchBrushInternal(
ULONG ulStyle,
COLORREF cr,
BOOL bPen
)
{
HBRUSH hbrush;
hbrush = hCreateHatchBrushInternal (ulStyle, cr, bPen);
return (hbrush);
}
/******************************Public*Routine******************************\
* NtGdiCreatePatternBrushInternal()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HBRUSH
APIENTRY
NtGdiCreatePatternBrushInternal(
HBITMAP hbm,
BOOL bPen,
BOOL b8X8
)
{
HBRUSH hbrush;
hbrush = GreCreatePatternBrushInternal(hbm,bPen,b8X8);
return (hbrush);
}
/******************************Public*Routine******************************\
* NtGdiCreateDIBBrush()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HBRUSH
APIENTRY
NtGdiCreateDIBBrush(
PVOID pv,
FLONG fl,
UINT cj,
BOOL b8X8,
BOOL bPen,
PVOID pClient
)
{
HBRUSH hbrRet;
PVOID pvTmp;
pvTmp = AllocFreeTmpBuffer(cj);
if (pvTmp)
{
hbrRet = (HBRUSH)1;
__try
{
ProbeForRead(pv,cj, sizeof(BYTE));
RtlCopyMemory(pvTmp,pv,cj);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// SetLastError(GetExceptionCode());
hbrRet = (HBRUSH)0;
}
if (hbrRet)
{
hbrRet = GreCreateDIBBrush(pvTmp,fl,cj,b8X8,bPen,pClient);
}
FreeTmpBuffer(pvTmp);
}
else
{
// SetLastError();
hbrRet = (HBRUSH)0;
}
return(hbrRet);
}
/**************************************************************************\
* GreCreatePatternBrushInternal(hbm, bPen)
*
* Creates a pattern brush from the bitmap passed in.
*
* History:
* Mon 24-Jun-1991 -by- Patrick Haluptzok [patrickh]
* Wrote it.
\**************************************************************************/
HBRUSH GreCreatePatternBrushInternal(
HBITMAP hbm,
BOOL bPen,
BOOL b8X8)
{
HBRUSH hbrReturn = (HBRUSH) 0;
SURFREF SurfBmo((HSURF)hbm);
if (SurfBmo.bValid())
{
if (SurfBmo.ps->bApiBitmap())
{
HBITMAP hbmClone;
if (b8X8)
hbmClone = hbmCreateClone(SurfBmo.ps,8,8);
else
hbmClone = hbmCreateClone(SurfBmo.ps,0,0);
if (hbmClone != (HBITMAP) 0)
{
XEPALOBJ pal(SurfBmo.ps->ppal());
BRUSHMEMOBJ brmo(hbmClone, hbm, pal.bIsMonochrome(), DIB_RGB_COLORS,
BR_IS_BITMAP, bPen);
if (brmo.bValid())
{
hbrReturn = brmo.hbrush();
brmo.vKeepIt();
} // hmgr logs error code
} // hmgr logs error code
}
else
{
WARNING("GreCreatePatternBrushInternal: Invalid surface");
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
}
}
else
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
}
return(hbrReturn);
}
HBRUSH GreCreatePatternBrush(HBITMAP hbm)
{
return(GreCreatePatternBrushInternal(hbm,FALSE,FALSE));
}
/******************************Public*Routine******************************\
* GreCreateDIBBrush
*
* Creates a DIB pattern brush.
*
* History:
* 02-Jun-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
HBRUSH
GreCreateDIBBrush(PVOID pv, FLONG fl, UINT cjMax, BOOL b8X8, BOOL bPen, PVOID pClient)
{
// Validate your parameters.
if ((pv == (PVOID) 0) ||
(cjMax < sizeof(BITMAPINFOHEADER)) ||
(((BITMAPINFOHEADER *) pv)->biSize > cjMax) ||
((fl != DIB_PAL_INDICES) &&
(fl != DIB_PAL_COLORS) &&
(fl != DIB_RGB_COLORS)))
{
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
return((HBRUSH) 0);
}
// Compute offset to the bits
UINT cjHeader = ((BITMAPINFOHEADER *) pv)->biSize;
PBYTE pjBits = ((PBYTE) pv) + cjHeader;
PUSHORT pusIndices;
UINT uiBits,cSize,uiCompression;
UINT cPalEntriesTotal;
LPBITMAPINFO pbmiTmp = NULL;
UINT cPalEntryMax;
uiBits = ((BITMAPINFOHEADER *) pv)->biBitCount;
pusIndices = (PUSHORT) pjBits;
cSize = sizeof(RGBQUAD);
cPalEntriesTotal = (UINT) ((BITMAPINFOHEADER *) pv)->biClrUsed;
uiCompression = ((BITMAPINFOHEADER *) pv)->biCompression;
// Check proper settings for compression.
if (uiCompression == BI_BITFIELDS)
{
cPalEntriesTotal = 3;
if (fl == DIB_PAL_COLORS)
fl = DIB_RGB_COLORS;
if ((uiBits != 16) && (uiBits != 32))
{
WARNING("CreateDIBPatternBrush given invalid data for BI_BITFIELDS\n");
return((HBRUSH) 0);
}
}
else if (uiCompression == BI_RGB)
{
switch(uiBits)
{
case 1:
cPalEntryMax = 2;
break;
case 4:
cPalEntryMax = 16;
break;
case 8:
cPalEntryMax = 256;
break;
case 16:
case 24:
case 32:
cPalEntryMax =
cPalEntriesTotal = 0;
// Win3.1 ignores the DIB_PAL_COLORS flag when non-indexed passed in.
if (fl == DIB_PAL_COLORS)
fl = DIB_RGB_COLORS;
break;
default:
WARNING("GreCreateDIBPatternBrushPt failed because of invalid bit count BI_RGB");
return((HBRUSH) 0);
}
if (cPalEntriesTotal == 0)
{
cPalEntriesTotal = cPalEntryMax;
}
else
cPalEntriesTotal = MIN(cPalEntryMax, cPalEntriesTotal);
}
else if (uiCompression == BI_RLE4)
{
if (uiBits != 4)
{
WARNING("CreateDIBrush RLE4 invalid bpp\n");
return((HBRUSH) 0);
}
if (cPalEntriesTotal == 0)
{
cPalEntriesTotal = 16;
}
}
else if (uiCompression == BI_RLE8)
{
if (uiBits != 8)
{
WARNING("CreateDIBrush RLE8 invalid bpp\n");
return((HBRUSH) 0);
}
if (cPalEntriesTotal == 0)
{
cPalEntriesTotal = 256;
}
}
else
{
// We don't support any other compressions for creating a brush on NT.
WARNING("Unknown Compression passed in - failed CreateDIBPatternBrush\n");
return((HBRUSH) 0);
}
// Check for the DIB_PAL_COLORS case.
if (fl == DIB_PAL_COLORS)
cSize = sizeof(USHORT);
else if (fl == DIB_PAL_INDICES)
cSize = 0;
// Validate that buffer is large enough to include color table. Guarantees
// that pjBits is within the bounds of the pv buffer passed in.
UINT cjColorTable = (((cSize * cPalEntriesTotal) + 3) & ~3);
if (cjColorTable > (cjMax - cjHeader))
{
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
return(0);
}
pjBits += cjColorTable; // now, pjBits = pv + cjHeader + cjColorTable
//
// Sundown: safe to truncate to INT since pjBits - pv will not exceed 4GB
// (validation above ensures that difference is <= cjMax)
//
INT cjBits = cjMax - (INT)(pjBits - (PBYTE)pv);
// Store the handle to bitmap just like a pattern brush, only mark
// it as a DIB.
HBITMAP hbmDIB;
FLONG flCreate = DIB_RGB_COLORS;
if (fl != DIB_RGB_COLORS)
{
flCreate = DIB_PAL_NONE;
}
hbmDIB = GreCreateDIBitmapReal(
(HDC) 0,
CBM_INIT | CBM_CREATEDIB,
pjBits,
(BITMAPINFO *)pv,
flCreate,
cjMax,
cjBits,
NULL,
0,
NULL,
CDBI_INTERNAL,
0,
NULL);
if (hbmDIB == (HBITMAP) 0)
{
WARNING("GreCreateDIBPatternBrush failed because GreCreateDIBitmap failed");
return((HBRUSH) 0);
}
if (b8X8)
{
SURFREF so((HSURF)hbmDIB);
ASSERTGDI(so.bValid(), "ERROR just created and already dead");
SIZEL sizlNew = so.ps->sizl();
if (so.ps->sizl().cx > 8)
{
sizlNew.cx = 8;
}
if (so.ps->sizl().cy > 8)
{
sizlNew.cy = 8;
}
so.ps->sizl(sizlNew);
}
// Now if we are creating a DIB_PAL_COLORS DIB brush we need to save the
// indices in the palette, so at runtime we can do the right thing.
if (fl == DIB_PAL_COLORS)
{
SURFREF so((HSURF)hbmDIB);
ASSERTGDI(so.bValid(), "ERROR GreCreateDIBBrush surface\n");
XEPALOBJ pal(so.ps->ppal());
pal.flPal(PAL_BRUSHHACK);
ASSERTGDI(pal.bValid(), "ERROR GreCreateDIBBrush pal.bValid\n");
ASSERTGDI(!pal.bIsPalDefault(), "ERROR GreCreateDIBBrush pal.bIsPal\n");
RtlCopyMemory((PUSHORT) pal.apalColorGet(), pusIndices,
cPalEntriesTotal << 1);
// Remember how big the color table is
pal.cColorTableLength(cPalEntriesTotal);
}
BRUSHMEMOBJ brmo(hbmDIB, (HBITMAP)pClient, FALSE, fl, BR_IS_DIB, bPen);
HBRUSH hbrRet;
if (brmo.bValid())
{
brmo.vKeepIt();
brmo.iUsage(fl);
hbrRet = brmo.hbrush();
}
else
{
bDeleteSurface((HSURF)hbmDIB);
hbrRet = (HBRUSH) 0;
}
return(hbrRet);
}
/******************************Public*Routine******************************\
* GreMarkUndeletableBrush
*
* Private API for USER.
*
* Mark a Brush as undeletable. This must be called before the Brush is ever
* passed out to an application.
*
* History:
* 13-Sep-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID GreMarkUndeletableBrush(HBRUSH hbr)
{
if(hbr == NULL)
{
WARNING("GreMarkUndeletableBrush called with NULL handle");
}
else if(!HmgMarkUndeletable((HOBJ)hbr, BRUSH_TYPE))
{
RIP("GreMarkUndeletableBrush failed to mark handle undeletable");
}
}
/******************************Public*Routine******************************\
* GreMarkDeletableBrush
*
* Private API for USER.
*
* This can be called anytime by USER to make the Brush deletable. We need
* to check they don't do this on our global objects.
*
* History:
* 13-Sep-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID GreMarkDeletableBrush(HBRUSH hbr)
{
BRUSHSELOBJ bro(hbr);
if (bro.bValid())
{
if(!bro.bIsGlobal())
{
if (hbr == NULL)
{
WARNING("GreMarkDeletableBrush called with NULL handle");
}
else if (!HmgMarkDeletable((HOBJ)hbr,BRUSH_TYPE))
{
RIP("GreMarkDeletableBrush failed to mark handle deletable");
}
}
}
else
{
WARNING("ERROR User gives Gdi invalid Brush");
}
}
/******************************Public*Routine******************************\
* GreCreatePen
*
* API creates a logical pen.
*
* History:
* 08-May-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
HPEN GreCreatePen(int iPenStyle, int ulWidth, COLORREF clrr, HBRUSH hbr)
{
HPEN hRet = 0;
PW32THREAD pthread = W32GetCurrentThread();
ASSERTGDI(!hbr,"GreCreatePen - hbr\n");
switch(iPenStyle)
{
case PS_NULL:
case PS_SOLID:
case PS_DASH:
case PS_DOT:
case PS_DASHDOT:
case PS_DASHDOTDOT:
case PS_INSIDEFRAME:
break;
default:
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
return((HPEN) 0);
}
hRet = GreExtCreatePen(iPenStyle,
ulWidth,
BS_SOLID,
clrr,
0,
0,
0,
(PULONG) NULL,
0,
TRUE,
hbr);
return (hRet);
}
/******************************Public*Routine******************************\
* GreExtCreatePen
*
* API creates an old-style or extended logical pen.
*
* History:
* 23-Jan-1992 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
HPEN GreExtCreatePen(
ULONG flPenStyle,
ULONG ulWidth,
ULONG iBrushStyle,
ULONG ulColor,
ULONG_PTR lClientHatch,
ULONG_PTR lHatch,
ULONG cstyle,
PULONG pulStyle,
ULONG cjDIB,
BOOL bOldStylePen,
HBRUSH hbrush)
{
BOOL bInvalidParm = FALSE;
BOOL bDefaultStyle = FALSE;
PFLOAT_LONG pstyle = (PFLOAT_LONG) NULL;
ULONG iType = flPenStyle & PS_TYPE_MASK;
ULONG ulStyle = flPenStyle & PS_STYLE_MASK;
ULONG iJoin;
ULONG iEndCap;
// We take the absoluate value of the integer width, like Win3 does:
LONG lWidthPen = ABS((LONG) ulWidth);
// Make sure no weird bits are set where none of our fields are:
if ((flPenStyle &
~(PS_TYPE_MASK | PS_STYLE_MASK | PS_ENDCAP_MASK | PS_JOIN_MASK)) != 0)
{
bInvalidParm = TRUE;
}
// Don't do any more parameter checking for NULL pens:
if (ulStyle == PS_NULL)
return(STOCKOBJ_NULLPEN);
// Do some more parameter checking.
switch(iType)
{
case PS_GEOMETRIC:
break;
case PS_COSMETIC:
if ((iBrushStyle == BS_SOLID) ||
((iBrushStyle == BS_HATCHED) &&
((lHatch == HS_SOLIDTEXTCLR) || (lHatch == HS_SOLIDBKCLR))))
{
break;
}
default:
bInvalidParm = TRUE;
}
if (lWidthPen != 1 && iType == PS_COSMETIC && !bOldStylePen)
{
bInvalidParm = TRUE;
}
switch(flPenStyle & PS_JOIN_MASK)
{
case PS_JOIN_ROUND: iJoin = JOIN_ROUND; break;
case PS_JOIN_BEVEL: iJoin = JOIN_BEVEL; break;
case PS_JOIN_MITER: iJoin = JOIN_MITER; break;
default:
bInvalidParm = TRUE;
}
switch(flPenStyle & PS_ENDCAP_MASK)
{
case PS_ENDCAP_ROUND: iEndCap = ENDCAP_ROUND; break;
case PS_ENDCAP_FLAT: iEndCap = ENDCAP_BUTT; break;
case PS_ENDCAP_SQUARE: iEndCap = ENDCAP_SQUARE; break;
default:
bInvalidParm = TRUE;
}
// Zero length array allowed iff not doing a user-supplied style,
// and aribtrarily limit the style array size:
if ((ulStyle == PS_USERSTYLE && cstyle == 0) ||
(ulStyle != PS_USERSTYLE && cstyle != 0) ||
cstyle > STYLE_MAX_COUNT)
{
bInvalidParm = TRUE;
}
if (iType == PS_GEOMETRIC)
{
switch(ulStyle)
{
case PS_DOT:
cstyle = sizeof(gaulGeometricDot) / sizeof(ULONG);
pulStyle = gaulGeometricDot;
break;
case PS_DASH:
cstyle = sizeof(gaulGeometricDash) / sizeof(ULONG);
pulStyle = gaulGeometricDash;
break;
case PS_DASHDOT:
cstyle = sizeof(gaulGeometricDashDot) / sizeof(ULONG);
pulStyle = gaulGeometricDashDot;
break;
case PS_DASHDOTDOT:
cstyle = sizeof(gaulGeometricDashDotDot) / sizeof(ULONG);
pulStyle = gaulGeometricDashDotDot;
break;
case PS_USERSTYLE:
case PS_SOLID:
break;
case PS_INSIDEFRAME:
break;
case PS_ALTERNATE:
default:
bInvalidParm = TRUE;
}
}
else
{
switch(ulStyle)
{
case PS_DOT:
cstyle = sizeof(galeCosmeticDot) / sizeof(LONG_FLOAT);
pstyle = &galeCosmeticDot[0].el;
bDefaultStyle = TRUE;
break;
case PS_DASH:
cstyle = sizeof(galeCosmeticDash) / sizeof(LONG_FLOAT);
pstyle = &galeCosmeticDash[0].el;
bDefaultStyle = TRUE;
break;
case PS_DASHDOT:
cstyle = sizeof(galeCosmeticDashDot) / sizeof(LONG_FLOAT);
pstyle = &galeCosmeticDashDot[0].el;
bDefaultStyle = TRUE;
break;
case PS_DASHDOTDOT:
cstyle = sizeof(galeCosmeticDashDotDot) / sizeof(LONG_FLOAT);
pstyle = &galeCosmeticDashDotDot[0].el;
bDefaultStyle = TRUE;
break;
case PS_USERSTYLE:
case PS_SOLID:
break;
case PS_ALTERNATE:
break;
case PS_INSIDEFRAME:
// Don't allow PS_INSIDEFRAME with new style cosmetic pens:
if (!bOldStylePen)
bInvalidParm = TRUE;
break;
default:
bInvalidParm = TRUE;
}
}
if (bInvalidParm)
{
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
return((HPEN) 0);
}
if (cstyle > 0 && pstyle == (PFLOAT_LONG) NULL)
{
pstyle = (PFLOAT_LONG) PALLOCNOZ(cstyle * sizeof(FLOAT_LONG),'ytsG');
if (pstyle == (PFLOAT_LONG) NULL)
{
SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
return((HPEN) 0);
}
PFLOAT_LONG ple = pstyle;
PFLOAT_LONG pleEnd = ple + cstyle;
if (iType == PS_COSMETIC || bOldStylePen)
{
// Handle cosmetic styles:
LONG lMin = 1;
LONG lMax = 1;
LONG lSum = 0;
while (ple < pleEnd)
{
ple->l = (LONG) *pulStyle;
lMin = MIN(lMin, ple->l);
lMax = MAX(lMax, ple->l);
lSum += ple->l;
pulStyle++;
ple++;
}
if (lMin <= 0 || lMax > STYLE_MAX_VALUE || lSum > STYLE_MAX_VALUE)
bInvalidParm = TRUE;
}
else
{
// Handle geometric styles:
LONG lSum = 0;
LONG lMin = 0;
while (ple < pleEnd)
{
LONG lLength = (LONG) *pulStyle;
// Default styles are based on multiples of the pen width:
if (ulStyle != PS_USERSTYLE)
{
// For round and square caps, shorten dashes and lengthen
// the gaps:
if (iEndCap != ENDCAP_BUTT)
lLength += ((ple - pstyle) & 1) ? 1 : -1;
// Don't really care about overflow on this multiplication:
lLength *= lWidthPen;
}
lMin = MIN(lMin, lLength);
lSum += lLength;
EFLOATEXT efLength(lLength);
efLength.vEfToF(ple->e);
pulStyle++;
ple++;
}
if (lMin < 0 || lSum <= 0)
bInvalidParm = TRUE;
}
if (bInvalidParm)
{
// At least one entry in the style array has to be non-zero:
VFREEMEM(pstyle);
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
return((HPEN) 0);
}
}
HBRUSH hbr = 0;
switch(iBrushStyle)
{
case BS_HOLLOW:
if (pstyle != (PFLOAT_LONG) NULL && !bDefaultStyle)
VFREEMEM(pstyle);
return(STOCKOBJ_NULLPEN);
case BS_SOLID:
hbr = hCreateSolidBrushInternal(ulColor,
TRUE,
hbrush,
(lWidthPen == 0) && (ulStyle == PS_SOLID));
break;
case BS_HATCHED:
hbr = hCreateHatchBrushInternal((ULONG) lHatch, ulColor, TRUE);
break;
case BS_PATTERN:
hbr = GreCreatePatternBrushInternal((HBITMAP) lHatch, TRUE,FALSE);
break;
case BS_DIBPATTERNPT:
hbr = GreCreateDIBBrush((PVOID) lHatch, ulColor,
(UINT) cjDIB, FALSE, TRUE, (PVOID)lClientHatch);
break;
case BS_DIBPATTERN:
RIP("BS_DIBPATTERN not supported in server");
default:
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
}
if (hbr == (HBRUSH) 0)
{
if (pstyle != (PFLOAT_LONG) NULL && !bDefaultStyle)
VFREEMEM(pstyle);
return((HPEN) 0);
}
BRUSHSELOBJ bso(hbr);
// we had better validate this since it is just a handle, it could already
// have been deleted.
if (!bso.bValid())
{
WARNING("Created invalid pen\n");
if (pstyle != (PFLOAT_LONG) NULL && !bDefaultStyle)
VFREEMEM(pstyle);
return((HPEN)0);
}
bso.vSetPen();
bso.flStylePen(flPenStyle);
bso.iEndCap(iEndCap);
bso.iJoin(iJoin);
bso.pstyle(pstyle);
bso.cstyle(cstyle);
bso.lWidthPen(lWidthPen);
if (bDefaultStyle)
bso.vSetDefaultStyle();
bso.lBrushStyle (iBrushStyle);
bso.lHatch (lClientHatch);
if (iType == PS_GEOMETRIC || bOldStylePen)
{
// Geometric line widths are FLOATs in the LINEATTRS structure, so
// we have to keep a FLOAT version of its width around too:
EFLOATEXT efWidth(lWidthPen);
FLOATL l_eWidth;
efWidth.vEfToF(l_eWidth);
bso.l_eWidthPen(l_eWidth);
}
// we need to add the pen/extpen bits to handle type for the client
HBRUSH hbrPen = (HBRUSH) MODIFY_HMGR_TYPE(hbr,LO_EXTPEN_TYPE);
if (bOldStylePen)
{
bso.vSetOldStylePen();
bso.vDisableDither();
if (ulStyle == PS_INSIDEFRAME)
{
bso.vEnableDither();
bso.vSetInsideFrame();
}
hbrPen = (HBRUSH) MODIFY_HMGR_TYPE(hbr,LO_PEN_TYPE);
}
else if (iType == PS_COSMETIC)
{
// For now, cosmetic lines must also be solid colored:
bso.vDisableDither();
}
else
{
// We also support inside frame for geometric ExtCreatePen pens:
if (ulStyle == PS_INSIDEFRAME)
{
bso.vSetInsideFrame();
}
}
// we now set the new pen handle type. This must be done while the pen is locked
HmgModifyHandleType((HOBJ)hbrPen);
ASSERTGDI(!bInvalidParm, "Invalid parm?");
return((HPEN) hbrPen);
}
/******************************Public*Routine******************************\
* GreCreatePenIndirect
*
* API creates a logical pen.
*
* History:
* 08-May-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
HPEN GreCreatePenIndirect(LPLOGPEN lpLogPen)
{
return(GreCreatePen((int)lpLogPen->lopnStyle,
(int)lpLogPen->lopnWidth.x,
lpLogPen->lopnColor,0));
}
/******************************Public*Routine******************************\
* GreMonoBitmap
*
* Is the specified bitmap monochromatic?
*
* History:
* 18-Mar-1992 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
BOOL NtGdiMonoBitmap(HBITMAP hbm)
{
SURFREF SurfBmo((HSURF)hbm);
if (!SurfBmo.bValid())
return(FALSE);
XEPALOBJ pal(SurfBmo.ps->ppal());
return(pal.bIsMonochrome());
}
/******************************Public*Routine******************************\
* GreGetObjectBitmapHandle
*
* Gets the handle of the bitmap associated with this brush
*
* History:
* 09-Mar-1992 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
HBITMAP GreGetObjectBitmapHandle(
HBRUSH hbr,
UINT *piUsage)
{
BRUSHSELOBJ ebo(hbr);
if (!ebo.bValid())
{
return((HBITMAP) 0);
}
HBITMAP hbm = ebo.hbmPattern();
if (ebo.bPalColors())
{
*piUsage = DIB_PAL_COLORS;
}
else if (ebo.bPalIndices())
{
*piUsage = DIB_PAL_INDICES;
}
else
{
*piUsage = DIB_RGB_COLORS;
}
return(hbm);
}