Implement clipping for bitblt operations

svn path=/trunk/; revision=4985
This commit is contained in:
Gé van Geldorp 2003-06-28 08:39:18 +00:00
parent 5e61f5b601
commit 9389c797ef
8 changed files with 253 additions and 104 deletions

View file

@ -7,6 +7,36 @@
#include "bitblt.h"
typedef BOOL (*PFN_VGABlt)(SURFOBJ*, SURFOBJ*, XLATEOBJ*, RECTL*, POINTL*);
typedef BOOL STDCALL (*PBLTRECTFUNC)(PSURFOBJ OutputObj,
PSURFOBJ InputObj,
PSURFOBJ Mask,
PXLATEOBJ ColorTranslation,
PRECTL OutputRect,
PPOINTL InputPoint,
PPOINTL MaskOrigin,
PBRUSHOBJ Brush,
PPOINTL BrushOrigin,
ROP4 Rop4);
static BOOL FASTCALL VGADDI_IntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2)
{
static const RECTL rclEmpty = { 0, 0, 0, 0 };
prcDst->left = max(prcSrc1->left, prcSrc2->left);
prcDst->right = min(prcSrc1->right, prcSrc2->right);
if (prcDst->left < prcDst->right)
{
prcDst->top = max(prcSrc1->top, prcSrc2->top);
prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
if (prcDst->top < prcDst->bottom) return(TRUE);
}
*prcDst = rclEmpty;
return(FALSE);
}
BOOL
DIBtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
@ -164,8 +194,10 @@ VGAtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
}
BOOL STDCALL
VGADDI_BltBrush(SURFOBJ* Dest, XLATEOBJ* ColorTranslation, RECTL* DestRect,
BRUSHOBJ* Brush, POINTL* BrushPoint, ROP4 Rop4)
VGADDI_BltBrush(PSURFOBJ Dest, PSURFOBJ Source, PSURFOBJ MaskSurf,
PXLATEOBJ ColorTranslation, PRECT DestRect,
PPOINTL SourcePoint, PPOINTL MaskPoint,
PBRUSHOBJ Brush, PPOINTL BrushPoint, ROP4 Rop4)
{
UCHAR SolidColor;
ULONG Left;
@ -267,8 +299,9 @@ VGADDI_BltBrush(SURFOBJ* Dest, XLATEOBJ* ColorTranslation, RECTL* DestRect,
}
BOOL STDCALL
VGADDI_BltSrc(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
RECTL *DestRect, POINTL *SourcePoint)
VGADDI_BltSrc(PSURFOBJ Dest, PSURFOBJ Source, PSURFOBJ Mask,
PXLATEOBJ ColorTranslation, PRECTL DestRect, PPOINTL SourcePoint,
PPOINTL MaskOrigin, PBRUSHOBJ Brush, PPOINTL BrushOrigin, ROP4 Rop4)
{
RECT_ENUM RectEnum;
BOOL EnumMore;
@ -308,9 +341,10 @@ VGADDI_BltSrc(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
}
BOOL STDCALL
VGADDI_BltMask(SURFOBJ *Dest, SURFOBJ *Mask, XLATEOBJ *ColorTranslation,
RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush,
POINTL* BrushPoint)
VGADDI_BltMask(PSURFOBJ Dest, PSURFOBJ Source, PSURFOBJ Mask,
PXLATEOBJ ColorTranslation, PRECTL DestRect,
PPOINTL SourcePoint, PPOINTL MaskPoint, BRUSHOBJ* Brush,
PPOINTL BrushPoint, ROP4 Rop4)
{
LONG i, j, dx, dy, idxColor, RGBulong = 0, c8;
BYTE *initial, *tMask, *lMask;
@ -355,36 +389,71 @@ DrvBitBlt(SURFOBJ *Dest,
POINTL *BrushPoint,
ROP4 rop4)
{
/* Punt bitblts with complex clipping to the GDI. */
if (Clip != NULL)
{
return(FALSE);
}
PBLTRECTFUNC BltRectFunc;
RECTL CombinedRect;
BOOL Ret;
RECT_ENUM RectEnum;
BOOL EnumMore;
unsigned i;
switch (rop4)
{
case BLACKNESS:
case PATCOPY:
case WHITENESS:
return(VGADDI_BltBrush(Dest, ColorTranslation, DestRect, Brush,
BrushPoint, rop4));
BltRectFunc = VGADDI_BltBrush;
break;
case SRCCOPY:
if (BMF_4BPP == Source->iBitmapFormat && BMF_4BPP == Dest->iBitmapFormat)
{
return(VGADDI_BltSrc(Dest, Source, ColorTranslation, DestRect,
SourcePoint));
{
BltRectFunc = VGADDI_BltSrc;
}
else
{
return FALSE;
return FALSE;
}
case 0xAACC:
return(VGADDI_BltMask(Dest, Mask, ColorTranslation, DestRect,
MaskPoint, Brush, BrushPoint));
BltRectFunc = VGADDI_BltMask;
break;
default:
return(FALSE);
return FALSE;
}
switch(NULL == Clip ? DC_TRIVIAL : Clip->iDComplexity)
{
case DC_TRIVIAL:
Ret = (*BltRectFunc)(Dest, Source, Mask, ColorTranslation, DestRect,
SourcePoint, MaskPoint, Brush, BrushPoint,
rop4);
break;
case DC_RECT:
// Clip the blt to the clip rectangle
VGADDI_IntersectRect(&CombinedRect, DestRect, &(Clip->rclBounds));
Ret = (*BltRectFunc)(Dest, Source, Mask, ColorTranslation, &CombinedRect,
SourcePoint, MaskPoint, Brush, BrushPoint,
rop4);
break;
case DC_COMPLEX:
Ret = TRUE;
CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT);
do
{
EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
for (i = 0; i < RectEnum.c; i++)
{
VGADDI_IntersectRect(&CombinedRect, DestRect, RectEnum.arcl + i);
Ret = (*BltRectFunc)(Dest, Source, Mask, ColorTranslation, &CombinedRect,
SourcePoint, MaskPoint, Brush, BrushPoint, rop4) &&
Ret;
}
}
while (EnumMore);
break;
}
return Ret;
}

View file

@ -98,6 +98,8 @@ typedef struct _DC
INT vportExtX; /* Viewport extent */
INT vportExtY;
CLIPOBJ *CombinedClip;
INT saveLevel;
WIN_DC_INFO w;

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: bitblt.c,v 1.20 2003/05/18 17:16:17 ea Exp $
/* $Id: bitblt.c,v 1.21 2003/06/28 08:39:18 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -46,6 +46,19 @@
#define NDEBUG
#include <win32k/debug1.h>
typedef BOOLEAN STDCALL (*PBLTRECTFUNC)(PSURFOBJ OutputObj,
PSURFGDI OutputGDI,
PSURFOBJ InputObj,
PSURFGDI InputGDI,
PSURFOBJ Mask,
PXLATEOBJ ColorTranslation,
PRECTL OutputRect,
PPOINTL InputPoint,
PPOINTL MaskOrigin,
PBRUSHOBJ Brush,
PPOINTL BrushOrigin,
ROP4 Rop4);
BOOL STDCALL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2)
{
static const RECTL rclEmpty = { 0, 0, 0, 0 };
@ -66,10 +79,19 @@ BOOL STDCALL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2)
return(FALSE);
}
static BOOL STDCALL
BltMask(SURFOBJ *Dest, PSURFGDI DestGDI, SURFOBJ *Mask,
RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush,
POINTL* BrushPoint)
static BOOLEAN STDCALL
BltMask(PSURFOBJ Dest,
PSURFGDI DestGDI,
PSURFOBJ Source,
PSURFGDI SourceGDI,
PSURFOBJ Mask,
PXLATEOBJ ColorTranslation,
PRECTL DestRect,
PPOINTL SourcePoint,
PPOINTL MaskPoint,
PBRUSHOBJ Brush,
PPOINTL BrushPoint,
ROP4 Rop4)
{
LONG i, j, dx, dy, c8;
BYTE *tMask, *lMask;
@ -108,10 +130,19 @@ BltMask(SURFOBJ *Dest, PSURFGDI DestGDI, SURFOBJ *Mask,
}
}
static BOOL STDCALL
BltPatCopy(SURFOBJ *Dest, PSURFGDI DestGDI, SURFOBJ *Mask,
RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush,
POINTL* BrushPoint)
static BOOLEAN STDCALL
BltPatCopy(PSURFOBJ Dest,
PSURFGDI DestGDI,
PSURFOBJ Source,
PSURFGDI SourceGDI,
PSURFOBJ Mask,
PXLATEOBJ ColorTranslation,
PRECTL DestRect,
PPOINTL SourcePoint,
PPOINTL MaskPoint,
PBRUSHOBJ Brush,
PPOINTL BrushPoint,
ROP4 Rop4)
{
// These functions are assigned if we're working with a DIB
// The assigned functions depend on the bitsPerPixel of the DIB
@ -127,6 +158,23 @@ BltPatCopy(SURFOBJ *Dest, PSURFGDI DestGDI, SURFOBJ *Mask,
return TRUE;
}
static BOOLEAN STDCALL
CallDibBitBlt(PSURFOBJ OutputObj,
PSURFGDI OutputGDI,
PSURFOBJ InputObj,
PSURFGDI InputGDI,
PSURFOBJ Mask,
PXLATEOBJ ColorTranslation,
PRECTL OutputRect,
PPOINTL InputPoint,
PPOINTL MaskOrigin,
PBRUSHOBJ Brush,
PPOINTL BrushOrigin,
ROP4 Rop4)
{
return OutputGDI->DIB_BitBlt(OutputObj, InputObj, OutputGDI, InputGDI, OutputRect, InputPoint, ColorTranslation);
}
INT abs(INT nm);
BOOL STDCALL
@ -140,12 +188,10 @@ EngBitBlt(SURFOBJ *DestObj,
POINTL *MaskOrigin,
BRUSHOBJ *Brush,
POINTL *BrushOrigin,
ROP4 rop4)
ROP4 Rop4)
{
BOOLEAN ret;
BYTE clippingType;
RECTL rclTmp;
POINTL ptlTmp;
RECTL CombinedRect;
RECT_ENUM RectEnum;
BOOL EnumMore;
PSURFGDI OutputGDI, InputGDI;
@ -157,6 +203,10 @@ EngBitBlt(SURFOBJ *DestObj,
INTENG_ENTER_LEAVE EnterLeaveDest;
PSURFOBJ InputObj;
PSURFOBJ OutputObj;
PBLTRECTFUNC BltRectFunc;
BOOLEAN Ret;
RECTL ClipRect;
unsigned i;
/* Check for degenerate case: if height or width of DestRect is 0 pixels there's
nothing to do */
@ -222,7 +272,7 @@ EngBitBlt(SURFOBJ *DestObj,
/* The code currently assumes there will be a source bitmap. This is not true when, for example, using this function to
* paint a brush pattern on the destination. */
if (NULL == InputObj && 0xaacc != rop4 && PATCOPY != rop4)
if (NULL == InputObj && 0xaacc != Rop4 && PATCOPY != Rop4)
{
DbgPrint("EngBitBlt: A source is currently required, even though not all operations require one (FIXME)\n");
return FALSE;
@ -236,79 +286,65 @@ EngBitBlt(SURFOBJ *DestObj,
clippingType = ClipRegion->iDComplexity;
}
if (0xaacc == rop4)
{
ret = BltMask(OutputObj, OutputGDI, Mask, &OutputRect, MaskOrigin, Brush, BrushOrigin);
IntEngLeave(&EnterLeaveDest);
IntEngLeave(&EnterLeaveSource);
return ret;
} else if (PATCOPY == rop4) {
ret = BltPatCopy(OutputObj, OutputGDI, Mask, &OutputRect, MaskOrigin, Brush, BrushOrigin);
IntEngLeave(&EnterLeaveDest);
IntEngLeave(&EnterLeaveSource);
return ret;
}
if (0xaacc == Rop4)
{
BltRectFunc = BltMask;
}
else if (PATCOPY == Rop4)
{
BltRectFunc = BltPatCopy;
}
else
{
BltRectFunc = CallDibBitBlt;
}
// We don't handle color translation just yet [we dont have to.. REMOVE REMOVE REMOVE]
switch(clippingType)
{
case DC_TRIVIAL:
OutputGDI->DIB_BitBlt(OutputObj, InputObj, OutputGDI, InputGDI, &OutputRect, &InputPoint, ColorTranslation);
IntEngLeave(&EnterLeaveDest);
IntEngLeave(&EnterLeaveSource);
return(TRUE);
Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
&OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin, Rop4);
break;
case DC_RECT:
// Clip the blt to the clip rectangle
EngIntersectRect(&rclTmp, &OutputRect, &ClipRegion->rclBounds);
ptlTmp.x = InputPoint.x + rclTmp.left - OutputRect.left;
ptlTmp.y = InputPoint.y + rclTmp.top - OutputRect.top;
IntEngLeave(&EnterLeaveDest);
IntEngLeave(&EnterLeaveSource);
return(TRUE);
ClipRect.left = ClipRegion->rclBounds.left + Translate.x;
ClipRect.right = ClipRegion->rclBounds.right + Translate.x;
ClipRect.top = ClipRegion->rclBounds.top + Translate.y;
ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y;
EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
&CombinedRect, &InputPoint, MaskOrigin, Brush, BrushOrigin, Rop4);
break;
case DC_COMPLEX:
Ret = TRUE;
CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT);
do
{
EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
do {
EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
if (RectEnum.c > 0)
{
RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
RECTL* prcl = &RectEnum.arcl[0];
do {
EngIntersectRect(prcl, prcl, &OutputRect);
ptlTmp.x = InputPoint.x + prcl->left - OutputRect.left;
ptlTmp.y = InputPoint.y + prcl->top - OutputRect.top;
prcl++;
} while (prcl < prclEnd);
}
} while(EnumMore);
IntEngLeave(&EnterLeaveDest);
IntEngLeave(&EnterLeaveSource);
return(TRUE);
for (i = 0; i < RectEnum.c; i++)
{
ClipRect.left = RectEnum.arcl[i].left + Translate.x;
ClipRect.right = RectEnum.arcl[i].right + Translate.x;
ClipRect.top = RectEnum.arcl[i].top + Translate.y;
ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
&CombinedRect, &InputPoint, MaskOrigin, Brush, BrushOrigin, Rop4) &&
Ret;
}
}
while(EnumMore);
break;
}
IntEngLeave(&EnterLeaveDest);
IntEngLeave(&EnterLeaveSource);
return(FALSE);
return Ret;
}
BOOL STDCALL
@ -322,7 +358,7 @@ IntEngBitBlt(SURFOBJ *DestObj,
POINTL *MaskOrigin,
BRUSHOBJ *Brush,
POINTL *BrushOrigin,
ROP4 rop4)
ROP4 Rop4)
{
BOOLEAN ret;
SURFGDI *DestGDI;
@ -345,12 +381,12 @@ IntEngBitBlt(SURFOBJ *DestObj,
/* Call the driver's DrvBitBlt if available */
if (NULL != DestGDI->BitBlt) {
ret = DestGDI->BitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, rop4);
DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, Rop4);
}
if (! ret) {
ret = EngBitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, rop4);
DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, Rop4);
}
MouseSafetyOnDrawEnd(DestObj, DestGDI);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: bitmaps.c,v 1.29 2003/06/06 10:17:44 gvg Exp $ */
/* $Id: bitmaps.c,v 1.30 2003/06/28 08:39:18 gvg Exp $ */
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
@ -110,7 +110,7 @@ BOOL STDCALL W32kBitBlt(HDC hDCDest,
// Perform the bitblt operation
Status = IntEngBitBlt(SurfDest, SurfSrc, NULL, NULL, XlateObj, &DestRect, &SourcePoint, NULL, NULL, NULL, ROP);
Status = IntEngBitBlt(SurfDest, SurfSrc, NULL, DCDest->CombinedClip, XlateObj, &DestRect, &SourcePoint, NULL, NULL, NULL, ROP);
if (XlateAlloc) EngDeleteXlate(XlateObj);
if (SurfDestAlloc) ExFreePool(SurfDest);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: brush.c,v 1.20 2003/05/18 17:16:17 ea Exp $
/* $Id: brush.c,v 1.21 2003/06/28 08:39:18 gvg Exp $
*/
@ -28,6 +28,7 @@
//#include <win32k/debug.h>
#include <include/object.h>
#include <include/inteng.h>
#include <include/error.h>
#define NDEBUG
#include <win32k/debug1.h>
@ -211,6 +212,7 @@ BOOL STDCALL W32kPatBlt(HDC hDC,
if (dc == NULL)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return(FALSE);
}
@ -243,7 +245,7 @@ BOOL STDCALL W32kPatBlt(HDC hDC,
ret = IntEngBitBlt(SurfObj,
NULL,
NULL,
NULL,
dc->CombinedClip,
NULL,
&DestRect,
NULL,

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: cliprgn.c,v 1.16 2003/06/26 21:52:40 gvg Exp $ */
/* $Id: cliprgn.c,v 1.17 2003/06/28 08:39:18 gvg Exp $ */
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
@ -26,6 +26,7 @@
#include <win32k/cliprgn.h>
#include <win32k/coord.h>
#include <include/error.h>
#include "../eng/clip.h"
#define NDEBUG
#include <win32k/debug1.h>
@ -33,6 +34,10 @@
VOID FASTCALL
CLIPPING_UpdateGCRegion(DC* Dc)
{
HRGN Combined;
PROSRGNDATA CombinedRegion;
#ifndef TODO
if (Dc->w.hGCClipRgn == NULL)
{
Dc->w.hGCClipRgn = W32kCreateRectRgn(0, 0, 0, 0);
@ -47,6 +52,36 @@ CLIPPING_UpdateGCRegion(DC* Dc)
W32kCombineRgn(Dc->w.hGCClipRgn, Dc->w.hClipRgn, Dc->w.hVisRgn,
RGN_AND);
}
#endif
Combined = W32kCreateRectRgn(0, 0, 0, 0);
ASSERT(NULL != Combined);
if (Dc->w.hClipRgn == NULL)
{
W32kCombineRgn(Combined, Dc->w.hVisRgn, 0, RGN_COPY);
}
else
{
W32kCombineRgn(Combined, Dc->w.hClipRgn, Dc->w.hVisRgn,
RGN_AND);
}
CombinedRegion = RGNDATA_LockRgn(Combined);
ASSERT(NULL != CombinedRegion);
if (NULL != Dc->CombinedClip)
{
IntEngDeleteClipRegion(Dc->CombinedClip);
}
Dc->CombinedClip = IntEngCreateClipRegion(CombinedRegion->rdh.nCount,
CombinedRegion->Buffer,
CombinedRegion->rdh.rcBound);
ASSERT(NULL != Dc->CombinedClip);
RGNDATA_UnlockRgn(Combined);
W32kDeleteObject(Combined);
}
HRGN WINAPI SaveVisRgn(HDC hdc)
@ -196,7 +231,7 @@ int STDCALL W32kSelectClipRgn(HDC hDC,
W32kDeleteObject(Copy);
return ERROR;
}
W32kOffsetRgn(Copy, dc->w.DCOrgX, dc->w.DCOrgX);
W32kOffsetRgn(Copy, dc->w.DCOrgX, dc->w.DCOrgY);
}
else
{

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: dc.c,v 1.61 2003/06/21 14:25:30 gvg Exp $
/* $Id: dc.c,v 1.62 2003/06/28 08:39:18 gvg Exp $
*
* DC.C - Device context functions
*
@ -37,6 +37,7 @@
#include <win32k/gdiobj.h>
#include <win32k/pen.h>
#include <win32k/text.h>
#include "../eng/clip.h"
#include "../eng/handle.h"
#include <include/inteng.h>
#include <include/eng.h>
@ -534,6 +535,10 @@ BOOL STDCALL W32kDeleteDC(HDC DCHandle)
{
W32kDeleteObject (DCToDelete->w.hVisRgn);
}
if (NULL != DCToDelete->CombinedClip)
{
IntEngDeleteClipRegion(DCToDelete->CombinedClip);
}
if (DCToDelete->w.hGCClipRgn)
{
W32kDeleteObject (DCToDelete->w.hGCClipRgn);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: text.c,v 1.33 2003/06/22 21:33:48 gvg Exp $ */
/* $Id: text.c,v 1.34 2003/06/28 08:39:18 gvg Exp $ */
#undef WIN32_LEAN_AND_MEAN
@ -1062,7 +1062,7 @@ W32kTextOut(HDC hDC,
SourceGlyphSurf = (PSURFOBJ)AccessUserObject((ULONG) HSourceGlyph);
// Use the font data as a mask to paint onto the DCs surface using a brush
IntEngBitBlt(SurfObj, NULL, SourceGlyphSurf, NULL, NULL, &DestRect, &SourcePoint, &MaskRect, Brush, &BrushOrigin, 0xAACC);
IntEngBitBlt(SurfObj, NULL, SourceGlyphSurf, dc->CombinedClip, NULL, &DestRect, &SourcePoint, &MaskRect, Brush, &BrushOrigin, 0xAACC);
EngDeleteSurface(HSourceGlyph);