mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 07:26:20 +00:00
In the beginning somebody created dc.c. And he saw that it was empty. So he quickly added some functions to it. And as there were so many nice dc functions, the dc.c quickly got populated with a lot of code. But dc.c must have still felt lonely,
so that people added more and more code, even completely unrelated code. Finally dc.c became a fat wastedump for all the code a developer didn't know where to put. Clean up this mess by splitting the 3600 line monster file into 5 files and moving some stuff into other files. svn path=/trunk/; revision=40182
This commit is contained in:
parent
8cb1d37567
commit
d7ab2a464e
9 changed files with 2467 additions and 2399 deletions
|
@ -130,8 +130,8 @@ typedef struct _DCLEVEL
|
|||
DWORD unk1_00000000;
|
||||
HGDIOBJ hdcSave;
|
||||
POINTL ptlBrushOrigin;
|
||||
PBRUSH pbrFill;
|
||||
PBRUSH pbrLine;
|
||||
PBRUSH pbrFill;
|
||||
PBRUSH pbrLine;
|
||||
PVOID plfnt; /* LFONTOBJ* (TEXTOBJ*) */
|
||||
HGDIOBJ hPath; /* HPATH */
|
||||
FLONG flPath;
|
||||
|
@ -278,4 +278,8 @@ INT FASTCALL IntGdiGetDeviceCaps(PDC,INT);
|
|||
|
||||
extern PPDEVOBJ pPrimarySurface;
|
||||
|
||||
BOOL FASTCALL
|
||||
IntPrepareDriverIfNeeded();
|
||||
extern PDEVOBJ PrimarySurface;
|
||||
|
||||
#endif /* not __WIN32K_DC_H */
|
||||
|
|
|
@ -66,6 +66,7 @@ IntFixIsotropicMapping(PDC dc)
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: don't use floating point in the kernel! use XFORMOBJ function
|
||||
BOOL FASTCALL
|
||||
IntGdiCombineTransform(LPXFORM XFormResult,
|
||||
LPXFORM xform1,
|
||||
|
@ -115,7 +116,7 @@ BOOL APIENTRY NtGdiCombineTransform(LPXFORM UnsafeXFormResult,
|
|||
return Ret;
|
||||
}
|
||||
|
||||
|
||||
// FIXME: remove me!
|
||||
int
|
||||
FASTCALL
|
||||
IntGetGraphicsMode(PDC dc)
|
||||
|
@ -1016,4 +1017,278 @@ NtGdiSetVirtualResolution(
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// FIXME: Don't use floating point in the kernel!
|
||||
BOOL FASTCALL
|
||||
DC_InvertXform(const XFORM *xformSrc,
|
||||
XFORM *xformDest)
|
||||
{
|
||||
FLOAT determinant;
|
||||
|
||||
determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21;
|
||||
if (determinant > -1e-12 && determinant < 1e-12)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
xformDest->eM11 = xformSrc->eM22 / determinant;
|
||||
xformDest->eM12 = -xformSrc->eM12 / determinant;
|
||||
xformDest->eM21 = -xformSrc->eM21 / determinant;
|
||||
xformDest->eM22 = xformSrc->eM11 / determinant;
|
||||
xformDest->eDx = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21;
|
||||
xformDest->eDy = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// FIXME: Don't use floating point in the kernel!
|
||||
VOID FASTCALL
|
||||
DC_UpdateXforms(PDC dc)
|
||||
{
|
||||
XFORM xformWnd2Vport;
|
||||
FLOAT scaleX, scaleY;
|
||||
PDC_ATTR pdcattr = dc->pdcattr;
|
||||
XFORM xformWorld2Vport, xformWorld2Wnd, xformVport2World;
|
||||
|
||||
/* Construct a transformation to do the window-to-viewport conversion */
|
||||
scaleX = (pdcattr->szlWindowExt.cx ? (FLOAT)pdcattr->szlViewportExt.cx / (FLOAT)pdcattr->szlWindowExt.cx : 0.0f);
|
||||
scaleY = (pdcattr->szlWindowExt.cy ? (FLOAT)pdcattr->szlViewportExt.cy / (FLOAT)pdcattr->szlWindowExt.cy : 0.0f);
|
||||
xformWnd2Vport.eM11 = scaleX;
|
||||
xformWnd2Vport.eM12 = 0.0;
|
||||
xformWnd2Vport.eM21 = 0.0;
|
||||
xformWnd2Vport.eM22 = scaleY;
|
||||
xformWnd2Vport.eDx = (FLOAT)pdcattr->ptlViewportOrg.x - scaleX * (FLOAT)pdcattr->ptlWindowOrg.x;
|
||||
xformWnd2Vport.eDy = (FLOAT)pdcattr->ptlViewportOrg.y - scaleY * (FLOAT)pdcattr->ptlWindowOrg.y;
|
||||
|
||||
/* Combine with the world transformation */
|
||||
MatrixS2XForm(&xformWorld2Vport, &dc->dclevel.mxWorldToDevice);
|
||||
MatrixS2XForm(&xformWorld2Wnd, &dc->dclevel.mxWorldToPage);
|
||||
IntGdiCombineTransform(&xformWorld2Vport, &xformWorld2Wnd, &xformWnd2Vport);
|
||||
|
||||
/* Create inverse of world-to-viewport transformation */
|
||||
MatrixS2XForm(&xformVport2World, &dc->dclevel.mxDeviceToWorld);
|
||||
if (DC_InvertXform(&xformWorld2Vport, &xformVport2World))
|
||||
{
|
||||
pdcattr->flXform &= ~DEVICE_TO_WORLD_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
pdcattr->flXform |= DEVICE_TO_WORLD_INVALID;
|
||||
}
|
||||
|
||||
XForm2MatrixS(&dc->dclevel.mxWorldToDevice, &xformWorld2Vport);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LONG FASTCALL
|
||||
IntCalcFillOrigin(PDC pdc)
|
||||
{
|
||||
pdc->ptlFillOrigin.x = pdc->dclevel.ptlBrushOrigin.x + pdc->ptlDCOrig.x;
|
||||
pdc->ptlFillOrigin.y = pdc->dclevel.ptlBrushOrigin.y + pdc->ptlDCOrig.y;
|
||||
|
||||
return pdc->ptlFillOrigin.y;
|
||||
}
|
||||
|
||||
VOID
|
||||
APIENTRY
|
||||
GdiSetDCOrg(HDC hDC, LONG Left, LONG Top, PRECTL prc)
|
||||
{
|
||||
PDC pdc;
|
||||
|
||||
pdc = DC_LockDc(hDC);
|
||||
if (!pdc) return;
|
||||
|
||||
pdc->ptlDCOrig.x = Left;
|
||||
pdc->ptlDCOrig.y = Top;
|
||||
|
||||
IntCalcFillOrigin(pdc);
|
||||
|
||||
if (prc) pdc->erclWindow = *prc;
|
||||
|
||||
DC_UnlockDc(pdc);
|
||||
}
|
||||
|
||||
|
||||
BOOL FASTCALL
|
||||
IntGdiGetDCOrg(PDC pDc, PPOINTL ppt)
|
||||
{
|
||||
*ppt = pDc->ptlDCOrig;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL APIENTRY
|
||||
GdiGetDCOrgEx(HDC hDC, PPOINTL ppt, PRECTL prc)
|
||||
{
|
||||
PDC pdc;
|
||||
|
||||
pdc = DC_LockDc(hDC);
|
||||
if (!pdc) return FALSE;
|
||||
|
||||
*prc = pdc->erclWindow;
|
||||
*ppt = pdc->ptlDCOrig;
|
||||
|
||||
DC_UnlockDc(pdc);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL FASTCALL
|
||||
IntGetAspectRatioFilter(PDC pDC,
|
||||
LPSIZE AspectRatio)
|
||||
{
|
||||
PDC_ATTR pdcattr;
|
||||
|
||||
pdcattr = pDC->pdcattr;
|
||||
|
||||
if ( pdcattr->flFontMapper & 1 ) // TRUE assume 1.
|
||||
{
|
||||
// "This specifies that Windows should only match fonts that have the
|
||||
// same aspect ratio as the display.", Programming Windows, Fifth Ed.
|
||||
AspectRatio->cx = pDC->ppdev->GDIInfo.ulLogPixelsX;
|
||||
AspectRatio->cy = pDC->ppdev->GDIInfo.ulLogPixelsY;
|
||||
}
|
||||
else
|
||||
{
|
||||
AspectRatio->cx = 0;
|
||||
AspectRatio->cy = 0;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
IntGetViewportExtEx(PDC pdc, LPSIZE pSize)
|
||||
{
|
||||
PDC_ATTR pdcattr;
|
||||
|
||||
/* Get a pointer to the dc attribute */
|
||||
pdcattr = pdc->pdcattr;
|
||||
|
||||
/* Check if we need to recalculate */
|
||||
if (pdcattr->flXform & PAGE_EXTENTS_CHANGED)
|
||||
{
|
||||
/* Check if we need to do isotropic fixup */
|
||||
if (pdcattr->iMapMode == MM_ISOTROPIC)
|
||||
{
|
||||
IntFixIsotropicMapping(pdc);
|
||||
}
|
||||
|
||||
/* Update xforms, CHECKME: really done here? */
|
||||
DC_UpdateXforms(pdc);
|
||||
}
|
||||
|
||||
/* Copy the viewport extension */
|
||||
*pSize = pdcattr->szlViewportExt;
|
||||
}
|
||||
|
||||
BOOL APIENTRY
|
||||
NtGdiGetDCPoint( HDC hDC, UINT iPoint, PPOINTL Point)
|
||||
{
|
||||
BOOL Ret = TRUE;
|
||||
DC *dc;
|
||||
POINTL SafePoint;
|
||||
SIZE Size;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
if(!Point)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RtlZeroMemory(&SafePoint, sizeof(POINT));
|
||||
|
||||
dc = DC_LockDc(hDC);
|
||||
if(!dc)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (iPoint)
|
||||
{
|
||||
case GdiGetViewPortExt:
|
||||
IntGetViewportExtEx(dc, &Size);
|
||||
SafePoint.x = Size.cx;
|
||||
SafePoint.y = Size.cy;
|
||||
break;
|
||||
case GdiGetWindowExt:
|
||||
IntGetWindowExtEx(dc, &Size);
|
||||
SafePoint.x = Size.cx;
|
||||
SafePoint.y = Size.cy;
|
||||
break;
|
||||
case GdiGetViewPortOrg:
|
||||
IntGetViewportOrgEx(dc, &SafePoint);
|
||||
break;
|
||||
case GdiGetWindowOrg:
|
||||
IntGetWindowOrgEx(dc, &SafePoint);
|
||||
break;
|
||||
case GdiGetDCOrg:
|
||||
Ret = IntGdiGetDCOrg(dc, &SafePoint);
|
||||
break;
|
||||
case GdiGetAspectRatioFilter:
|
||||
Ret = IntGetAspectRatioFilter(dc, &Size);
|
||||
SafePoint.x = Size.cx;
|
||||
SafePoint.y = Size.cy;
|
||||
break;
|
||||
default:
|
||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||
Ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Ret)
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForWrite(Point,
|
||||
sizeof(POINT),
|
||||
1);
|
||||
*Point = SafePoint;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastNtError(Status);
|
||||
DC_UnlockDc(dc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DC_UnlockDc(dc);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
APIENTRY
|
||||
NtGdiGetBoundsRect(
|
||||
IN HDC hdc,
|
||||
OUT LPRECT prc,
|
||||
IN DWORD f)
|
||||
{
|
||||
DPRINT1("stub\n");
|
||||
return DCB_RESET; /* bounding rectangle always empty */
|
||||
}
|
||||
|
||||
DWORD
|
||||
APIENTRY
|
||||
NtGdiSetBoundsRect(
|
||||
IN HDC hdc,
|
||||
IN LPRECT prc,
|
||||
IN DWORD f)
|
||||
{
|
||||
DPRINT1("stub\n");
|
||||
return DCB_DISABLE; /* bounding rectangle always empty */
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
|
138
reactos/subsystems/win32/win32k/objects/dcattr.c
Normal file
138
reactos/subsystems/win32/win32k/objects/dcattr.c
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: Functions for creation and destruction of DCs
|
||||
* FILE: subsystem/win32/win32k/objects/dcattr.c
|
||||
* PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
|
||||
*/
|
||||
|
||||
#include <w32k.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
DC_AllocateDcAttr(HDC hDC)
|
||||
{
|
||||
PVOID NewMem = NULL;
|
||||
PDC pDC;
|
||||
HANDLE Pid = NtCurrentProcess();
|
||||
ULONG MemSize = sizeof(DC_ATTR); //PAGE_SIZE it will allocate that size
|
||||
|
||||
NTSTATUS Status = ZwAllocateVirtualMemory(Pid,
|
||||
&NewMem,
|
||||
0,
|
||||
&MemSize,
|
||||
MEM_COMMIT|MEM_RESERVE,
|
||||
PAGE_READWRITE);
|
||||
KeEnterCriticalRegion();
|
||||
{
|
||||
INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)hDC);
|
||||
PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
|
||||
// FIXME: dc could have been deleted!!! use GDIOBJ_InsertUserData
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
RtlZeroMemory(NewMem, MemSize);
|
||||
Entry->UserData = NewMem;
|
||||
DPRINT("DC_ATTR allocated! 0x%x\n",NewMem);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("DC_ATTR not allocated!\n");
|
||||
}
|
||||
}
|
||||
KeLeaveCriticalRegion();
|
||||
pDC = DC_LockDc(hDC);
|
||||
ASSERT(pDC->pdcattr == &pDC->dcattr);
|
||||
if(NewMem)
|
||||
{
|
||||
pDC->pdcattr = NewMem; // Store pointer
|
||||
}
|
||||
DC_UnlockDc(pDC);
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
DC_FreeDcAttr(HDC DCToFree )
|
||||
{
|
||||
HANDLE Pid = NtCurrentProcess();
|
||||
PDC pDC = DC_LockDc(DCToFree);
|
||||
if (pDC->pdcattr == &pDC->dcattr) return; // Internal DC object!
|
||||
pDC->pdcattr = &pDC->dcattr;
|
||||
DC_UnlockDc(pDC);
|
||||
|
||||
KeEnterCriticalRegion();
|
||||
{
|
||||
INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)DCToFree);
|
||||
PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
|
||||
if(Entry->UserData)
|
||||
{
|
||||
ULONG MemSize = sizeof(DC_ATTR); //PAGE_SIZE;
|
||||
NTSTATUS Status = ZwFreeVirtualMemory(Pid,
|
||||
&Entry->UserData,
|
||||
&MemSize,
|
||||
MEM_RELEASE);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("DC_FreeDC DC_ATTR 0x%x\n", Entry->UserData);
|
||||
Entry->UserData = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
KeLeaveCriticalRegion();
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
VOID
|
||||
CopytoUserDcAttr(PDC dc, PDC_ATTR pdcattr)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
dc->dcattr.mxWorldToDevice = dc->dclevel.mxWorldToDevice;
|
||||
dc->dcattr.mxDeviceToWorld = dc->dclevel.mxDeviceToWorld;
|
||||
dc->dcattr.mxWorldToPage = dc->dclevel.mxWorldToPage;
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForWrite( pdcattr,
|
||||
sizeof(DC_ATTR),
|
||||
1);
|
||||
RtlCopyMemory( pdcattr,
|
||||
&dc->dcattr,
|
||||
sizeof(DC_ATTR));
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
// FIXME: wtf? 2 functions, where one has a typo in the name????
|
||||
BOOL
|
||||
FASTCALL
|
||||
DCU_SyncDcAttrtoUser(PDC dc)
|
||||
{
|
||||
PDC_ATTR pdcattr = dc->pdcattr;
|
||||
|
||||
if (pdcattr == &dc->dcattr) return TRUE; // No need to copy self.
|
||||
ASSERT(pdcattr);
|
||||
CopytoUserDcAttr( dc, pdcattr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
DCU_SynchDcAttrtoUser(HDC hDC)
|
||||
{
|
||||
BOOL Ret;
|
||||
PDC pDC = DC_LockDc ( hDC );
|
||||
if (!pDC) return FALSE;
|
||||
Ret = DCU_SyncDcAttrtoUser(pDC);
|
||||
DC_UnlockDc( pDC );
|
||||
return Ret;
|
||||
}
|
||||
|
680
reactos/subsystems/win32/win32k/objects/dclife.c
Normal file
680
reactos/subsystems/win32/win32k/objects/dclife.c
Normal file
|
@ -0,0 +1,680 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: Functions for creation and destruction of DCs
|
||||
* FILE: subsystem/win32/win32k/objects/dclife.c
|
||||
* PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
|
||||
*/
|
||||
|
||||
#include <w32k.h>
|
||||
#include <bugcodes.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/** Internal functions ********************************************************/
|
||||
|
||||
HDC FASTCALL
|
||||
DC_AllocDC(PUNICODE_STRING Driver)
|
||||
{
|
||||
PDC NewDC;
|
||||
PDC_ATTR pdcattr;
|
||||
HDC hDC;
|
||||
PWSTR Buf = NULL;
|
||||
XFORM xformTemplate;
|
||||
|
||||
if (Driver != NULL)
|
||||
{
|
||||
Buf = ExAllocatePoolWithTag(PagedPool, Driver->MaximumLength, TAG_DC);
|
||||
if(!Buf)
|
||||
{
|
||||
DPRINT1("ExAllocatePoolWithTag failed\n");
|
||||
return NULL;
|
||||
}
|
||||
RtlCopyMemory(Buf, Driver->Buffer, Driver->MaximumLength);
|
||||
}
|
||||
|
||||
NewDC = (PDC)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_DC);
|
||||
if(!NewDC)
|
||||
{
|
||||
if(Buf)
|
||||
{
|
||||
ExFreePoolWithTag(Buf, TAG_DC);
|
||||
}
|
||||
DPRINT1("GDIOBJ_AllocObjWithHandle failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hDC = NewDC->BaseObject.hHmgr;
|
||||
|
||||
NewDC->pdcattr = &NewDC->dcattr;
|
||||
DC_AllocateDcAttr(hDC);
|
||||
|
||||
if (Driver != NULL)
|
||||
{
|
||||
RtlCopyMemory(&NewDC->rosdc.DriverName, Driver, sizeof(UNICODE_STRING));
|
||||
NewDC->rosdc.DriverName.Buffer = Buf;
|
||||
}
|
||||
pdcattr = NewDC->pdcattr;
|
||||
|
||||
xformTemplate.eM11 = 1.0f;
|
||||
xformTemplate.eM12 = 0.0f;
|
||||
xformTemplate.eM21 = 0.0f;
|
||||
xformTemplate.eM22 = 1.0f;
|
||||
xformTemplate.eDx = 0.0f;
|
||||
xformTemplate.eDy = 0.0f;
|
||||
XForm2MatrixS(&NewDC->dclevel.mxWorldToDevice, &xformTemplate);
|
||||
XForm2MatrixS(&NewDC->dclevel.mxDeviceToWorld, &xformTemplate);
|
||||
XForm2MatrixS(&NewDC->dclevel.mxWorldToPage, &xformTemplate);
|
||||
|
||||
// Setup syncing bits for the dcattr data packets.
|
||||
pdcattr->flXform = DEVICE_TO_PAGE_INVALID;
|
||||
|
||||
pdcattr->ulDirty_ = 0; // Server side
|
||||
|
||||
pdcattr->iMapMode = MM_TEXT;
|
||||
pdcattr->iGraphicsMode = GM_COMPATIBLE;
|
||||
pdcattr->jFillMode = ALTERNATE;
|
||||
|
||||
pdcattr->szlWindowExt.cx = 1; // Float to Int,,, WRONG!
|
||||
pdcattr->szlWindowExt.cy = 1;
|
||||
pdcattr->szlViewportExt.cx = 1;
|
||||
pdcattr->szlViewportExt.cy = 1;
|
||||
|
||||
pdcattr->crForegroundClr = 0;
|
||||
pdcattr->ulForegroundClr = 0;
|
||||
|
||||
pdcattr->ulBackgroundClr = 0xffffff;
|
||||
pdcattr->crBackgroundClr = 0xffffff;
|
||||
|
||||
pdcattr->ulPenClr = RGB( 0, 0, 0 );
|
||||
pdcattr->crPenClr = RGB( 0, 0, 0 );
|
||||
|
||||
pdcattr->ulBrushClr = RGB( 255, 255, 255 ); // Do this way too.
|
||||
pdcattr->crBrushClr = RGB( 255, 255, 255 );
|
||||
|
||||
//// This fixes the default brush and pen settings. See DC_InitDC.
|
||||
|
||||
/* Create the default fill brush */
|
||||
pdcattr->hbrush = NtGdiGetStockObject( WHITE_BRUSH );
|
||||
NewDC->dclevel.pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush);
|
||||
EBRUSHOBJ_vInit(&NewDC->eboFill, NewDC->dclevel.pbrFill, NULL);
|
||||
|
||||
/* Create the default pen / line brush */
|
||||
pdcattr->hpen = NtGdiGetStockObject( BLACK_PEN );
|
||||
NewDC->dclevel.pbrLine = PEN_ShareLockPen(pdcattr->hpen);
|
||||
EBRUSHOBJ_vInit(&NewDC->eboLine, NewDC->dclevel.pbrFill, NULL);
|
||||
|
||||
|
||||
pdcattr->hlfntNew = NtGdiGetStockObject(SYSTEM_FONT);
|
||||
TextIntRealizeFont(pdcattr->hlfntNew,NULL);
|
||||
|
||||
NewDC->dclevel.hpal = NtGdiGetStockObject(DEFAULT_PALETTE);
|
||||
NewDC->dclevel.laPath.eMiterLimit = 10.0;
|
||||
|
||||
DC_UnlockDc(NewDC);
|
||||
|
||||
return hDC;
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
DC_FreeDC(HDC DCToFree)
|
||||
{
|
||||
DC_FreeDcAttr(DCToFree);
|
||||
if(!IsObjectDead( DCToFree ))
|
||||
{
|
||||
if (!GDIOBJ_FreeObjByHandle(DCToFree, GDI_OBJECT_TYPE_DC))
|
||||
{
|
||||
DPRINT1("DC_FreeDC failed\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n",DCToFree);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL INTERNAL_CALL
|
||||
DC_Cleanup(PVOID ObjectBody)
|
||||
{
|
||||
PDC pDC = (PDC)ObjectBody;
|
||||
if (pDC->rosdc.DriverName.Buffer)
|
||||
ExFreePoolWithTag(pDC->rosdc.DriverName.Buffer, TAG_DC);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
DC_SetOwnership(HDC hDC, PEPROCESS Owner)
|
||||
{
|
||||
PDC pDC;
|
||||
|
||||
if(!GDIOBJ_SetOwnership(hDC, Owner)) return FALSE;
|
||||
pDC = DC_LockDc(hDC);
|
||||
if (pDC)
|
||||
{
|
||||
if (pDC->rosdc.hClipRgn)
|
||||
{
|
||||
if(!GDIOBJ_SetOwnership(pDC->rosdc.hClipRgn, Owner)) return FALSE;
|
||||
}
|
||||
if (pDC->rosdc.hVisRgn)
|
||||
{
|
||||
if(!GDIOBJ_SetOwnership(pDC->rosdc.hVisRgn, Owner)) return FALSE;
|
||||
}
|
||||
if (pDC->rosdc.hGCClipRgn)
|
||||
{
|
||||
if(!GDIOBJ_SetOwnership(pDC->rosdc.hGCClipRgn, Owner)) return FALSE;
|
||||
}
|
||||
if (pDC->dclevel.hPath)
|
||||
{
|
||||
if(!GDIOBJ_SetOwnership(pDC->dclevel.hPath, Owner)) return FALSE;
|
||||
}
|
||||
DC_UnlockDc(pDC);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
HDC FASTCALL
|
||||
IntGdiCreateDC(PUNICODE_STRING Driver,
|
||||
PUNICODE_STRING Device,
|
||||
PVOID pUMdhpdev,
|
||||
CONST PDEVMODEW InitData,
|
||||
BOOL CreateAsIC)
|
||||
{
|
||||
HDC hdc;
|
||||
PDC pdc;
|
||||
PDC_ATTR pdcattr;
|
||||
HRGN hVisRgn;
|
||||
UNICODE_STRING StdDriver;
|
||||
BOOL calledFromUser;
|
||||
|
||||
RtlInitUnicodeString(&StdDriver, L"DISPLAY");
|
||||
|
||||
DPRINT("DriverName: %wZ, DeviceName: %wZ\n", Driver, Device);
|
||||
|
||||
if (NULL == Driver || 0 == RtlCompareUnicodeString(Driver, &StdDriver, TRUE))
|
||||
{
|
||||
if (CreateAsIC)
|
||||
{
|
||||
if (! IntPrepareDriverIfNeeded())
|
||||
{
|
||||
/* Here, we have two possibilities:
|
||||
* a) return NULL, and hope that the caller
|
||||
* won't call us in a loop
|
||||
* b) bugcheck, but caller is unable to
|
||||
* react on the problem
|
||||
*/
|
||||
/*DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
|
||||
return NULL;*/
|
||||
KeBugCheck(VIDEO_DRIVER_INIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
calledFromUser = UserIsEntered();
|
||||
if (!calledFromUser){
|
||||
UserEnterExclusive();
|
||||
}
|
||||
|
||||
if (! co_IntGraphicsCheck(TRUE))
|
||||
{
|
||||
if (!calledFromUser){
|
||||
UserLeave();
|
||||
}
|
||||
DPRINT1("Unable to initialize graphics, returning NULL dc\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!calledFromUser){
|
||||
UserLeave();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for existing DC object */
|
||||
if ((hdc = DC_FindOpenDC(Driver)) != NULL)
|
||||
{
|
||||
hdc = NtGdiCreateCompatibleDC(hdc);
|
||||
if (!hdc)
|
||||
DPRINT1("NtGdiCreateCompatibleDC() failed\n");
|
||||
return hdc;
|
||||
}
|
||||
|
||||
/* Allocate a DC object */
|
||||
if ((hdc = DC_AllocDC(Driver)) == NULL)
|
||||
{
|
||||
DPRINT1("DC_AllocDC() failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdc = DC_LockDc( hdc );
|
||||
if ( !pdc )
|
||||
{
|
||||
DC_FreeDC( hdc );
|
||||
DPRINT1("DC_LockDc() failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdcattr = pdc->pdcattr;
|
||||
|
||||
pdc->dctype = DC_TYPE_DIRECT;
|
||||
|
||||
pdc->dhpdev = PrimarySurface.hPDev;
|
||||
if(pUMdhpdev) pUMdhpdev = pdc->dhpdev; // set DHPDEV for device.
|
||||
pdc->ppdev = (PVOID)&PrimarySurface;
|
||||
pdc->rosdc.hBitmap = (HBITMAP)PrimarySurface.pSurface;
|
||||
// ATM we only have one display.
|
||||
pdcattr->ulDirty_ |= DC_PRIMARY_DISPLAY;
|
||||
|
||||
pdc->rosdc.bitsPerPixel = pdc->ppdev->GDIInfo.cBitsPixel *
|
||||
pdc->ppdev->GDIInfo.cPlanes;
|
||||
DPRINT("Bits per pel: %u\n", pdc->rosdc.bitsPerPixel);
|
||||
|
||||
pdc->flGraphicsCaps = PrimarySurface.DevInfo.flGraphicsCaps;
|
||||
pdc->flGraphicsCaps2 = PrimarySurface.DevInfo.flGraphicsCaps2;
|
||||
|
||||
pdc->dclevel.hpal = NtGdiGetStockObject(DEFAULT_PALETTE);
|
||||
|
||||
pdcattr->jROP2 = R2_COPYPEN;
|
||||
|
||||
pdc->erclWindow.top = pdc->erclWindow.left = 0;
|
||||
pdc->erclWindow.right = pdc->ppdev->GDIInfo.ulHorzRes;
|
||||
pdc->erclWindow.bottom = pdc->ppdev->GDIInfo.ulVertRes;
|
||||
pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE; // Default is CCW.
|
||||
|
||||
pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0);
|
||||
|
||||
hVisRgn = NtGdiCreateRectRgn(0, 0, pdc->ppdev->GDIInfo.ulHorzRes,
|
||||
pdc->ppdev->GDIInfo.ulVertRes);
|
||||
|
||||
if (!CreateAsIC)
|
||||
{
|
||||
pdc->pSurfInfo = NULL;
|
||||
// pdc->dclevel.pSurface =
|
||||
DC_UnlockDc( pdc );
|
||||
|
||||
/* Initialize the DC state */
|
||||
DC_InitDC(hdc);
|
||||
IntGdiSetTextColor(hdc, RGB(0, 0, 0));
|
||||
IntGdiSetBkColor(hdc, RGB(255, 255, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* From MSDN2:
|
||||
The CreateIC function creates an information context for the specified device.
|
||||
The information context provides a fast way to get information about the
|
||||
device without creating a device context (DC). However, GDI drawing functions
|
||||
cannot accept a handle to an information context.
|
||||
*/
|
||||
pdc->dctype = DC_TYPE_INFO;
|
||||
// pdc->pSurfInfo =
|
||||
pdc->dclevel.pSurface = NULL;
|
||||
pdcattr->crBackgroundClr = pdcattr->ulBackgroundClr = RGB(255, 255, 255);
|
||||
pdcattr->crForegroundClr = RGB(0, 0, 0);
|
||||
DC_UnlockDc( pdc );
|
||||
}
|
||||
|
||||
if (hVisRgn)
|
||||
{
|
||||
GdiSelectVisRgn(hdc, hVisRgn);
|
||||
NtGdiDeleteObject(hVisRgn);
|
||||
}
|
||||
|
||||
IntGdiSetTextAlign(hdc, TA_TOP);
|
||||
IntGdiSetBkMode(hdc, OPAQUE);
|
||||
|
||||
return hdc;
|
||||
}
|
||||
|
||||
|
||||
HDC APIENTRY
|
||||
NtGdiOpenDCW( PUNICODE_STRING Device,
|
||||
DEVMODEW *InitData,
|
||||
PUNICODE_STRING pustrLogAddr,
|
||||
ULONG iType,
|
||||
HANDLE hspool,
|
||||
VOID *pDriverInfo2,
|
||||
VOID *pUMdhpdev )
|
||||
{
|
||||
UNICODE_STRING SafeDevice;
|
||||
DEVMODEW SafeInitData;
|
||||
PVOID Dhpdev;
|
||||
HDC Ret;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
if(InitData)
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
if (pUMdhpdev)
|
||||
{
|
||||
ProbeForWrite(pUMdhpdev,
|
||||
sizeof(PVOID),
|
||||
1);
|
||||
}
|
||||
ProbeForRead(InitData,
|
||||
sizeof(DEVMODEW),
|
||||
1);
|
||||
RtlCopyMemory(&SafeInitData,
|
||||
InitData,
|
||||
sizeof(DEVMODEW));
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END;
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastNtError(Status);
|
||||
return NULL;
|
||||
}
|
||||
/* FIXME - InitData can have some more bytes! */
|
||||
}
|
||||
|
||||
if(Device)
|
||||
{
|
||||
Status = IntSafeCopyUnicodeString(&SafeDevice, Device);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastNtError(Status);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Ret = IntGdiCreateDC(Device ? &SafeDevice : NULL,
|
||||
NULL,
|
||||
pUMdhpdev ? &Dhpdev : NULL,
|
||||
InitData ? &SafeInitData : NULL,
|
||||
(BOOL) iType); // FALSE 0 DCW, TRUE 1 ICW
|
||||
|
||||
if (pUMdhpdev) pUMdhpdev = Dhpdev;
|
||||
|
||||
return Ret;
|
||||
|
||||
}
|
||||
|
||||
HDC FASTCALL
|
||||
IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC)
|
||||
{
|
||||
HDC hDC;
|
||||
UNICODE_STRING DriverName;
|
||||
RtlInitUnicodeString(&DriverName, L"DISPLAY");
|
||||
|
||||
if (DcType != DC_TYPE_MEMORY)
|
||||
hDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, (DcType == DC_TYPE_INFO));
|
||||
else
|
||||
hDC = NtGdiCreateCompatibleDC(NULL); // OH~ Yuck! I think I taste vomit in my mouth!
|
||||
//
|
||||
// There is room to grow here~
|
||||
//
|
||||
|
||||
//
|
||||
// If NULL, first time through! Build the default (was window) dc!
|
||||
//
|
||||
if (hDC && !defaultDCstate) // Ultra HAX! Dedicated to GvG!
|
||||
{ // This is a cheesy way to do this.
|
||||
PDC dc = DC_LockDc ( hDC );
|
||||
defaultDCstate = ExAllocatePoolWithTag(PagedPool, sizeof(DC), TAG_DC);
|
||||
if (!defaultDCstate)
|
||||
{
|
||||
DC_UnlockDc( dc );
|
||||
return NULL;
|
||||
}
|
||||
RtlZeroMemory(defaultDCstate, sizeof(DC));
|
||||
defaultDCstate->pdcattr = &defaultDCstate->dcattr;
|
||||
IntGdiCopyToSaveState(dc, defaultDCstate);
|
||||
DC_UnlockDc( dc );
|
||||
}
|
||||
return hDC;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
IntGdiDeleteDC(HDC hDC, BOOL Force)
|
||||
{
|
||||
PDC DCToDelete = DC_LockDc(hDC);
|
||||
|
||||
if (DCToDelete == NULL)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(!Force)
|
||||
{
|
||||
if (DCToDelete->fs & DC_FLAG_PERMANENT)
|
||||
{
|
||||
DPRINT1("No! You Naughty Application!\n");
|
||||
DC_UnlockDc( DCToDelete );
|
||||
return UserReleaseDC(NULL, hDC, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* First delete all saved DCs */
|
||||
while (DCToDelete->dclevel.lSaveDepth)
|
||||
{
|
||||
PDC savedDC;
|
||||
HDC savedHDC;
|
||||
|
||||
savedHDC = DC_GetNextDC (DCToDelete);
|
||||
savedDC = DC_LockDc (savedHDC);
|
||||
if (savedDC == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC));
|
||||
DCToDelete->dclevel.lSaveDepth--;
|
||||
DC_UnlockDc( savedDC );
|
||||
IntGdiDeleteDC(savedHDC, Force);
|
||||
}
|
||||
|
||||
/* Free GDI resources allocated to this DC */
|
||||
if (!(DCToDelete->dclevel.flPath & DCPATH_SAVESTATE))
|
||||
{
|
||||
/*
|
||||
NtGdiSelectPen (DCHandle, STOCK_BLACK_PEN);
|
||||
NtGdiSelectBrush (DCHandle, STOCK_WHITE_BRUSH);
|
||||
NtGdiSelectFont (DCHandle, STOCK_SYSTEM_FONT);
|
||||
DC_LockDC (DCHandle); NtGdiSelectXxx does not recognize stock objects yet */
|
||||
if (DCToDelete->rosdc.XlateBrush != NULL)
|
||||
EngDeleteXlate(DCToDelete->rosdc.XlateBrush);
|
||||
if (DCToDelete->rosdc.XlatePen != NULL)
|
||||
EngDeleteXlate(DCToDelete->rosdc.XlatePen);
|
||||
}
|
||||
if (DCToDelete->rosdc.hClipRgn)
|
||||
{
|
||||
NtGdiDeleteObject (DCToDelete->rosdc.hClipRgn);
|
||||
}
|
||||
if (DCToDelete->rosdc.hVisRgn)
|
||||
{
|
||||
NtGdiDeleteObject (DCToDelete->rosdc.hVisRgn);
|
||||
}
|
||||
if (NULL != DCToDelete->rosdc.CombinedClip)
|
||||
{
|
||||
IntEngDeleteClipRegion(DCToDelete->rosdc.CombinedClip);
|
||||
}
|
||||
if (DCToDelete->rosdc.hGCClipRgn)
|
||||
{
|
||||
NtGdiDeleteObject (DCToDelete->rosdc.hGCClipRgn);
|
||||
}
|
||||
PATH_Delete(DCToDelete->dclevel.hPath);
|
||||
|
||||
DC_UnlockDc( DCToDelete );
|
||||
DC_FreeDC ( hDC );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HDC FASTCALL
|
||||
DC_FindOpenDC(PUNICODE_STRING Driver)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Initialize some common fields in the Device Context structure.
|
||||
*/
|
||||
VOID FASTCALL
|
||||
DC_InitDC(HDC DCHandle)
|
||||
{
|
||||
// NtGdiRealizeDefaultPalette(DCHandle);
|
||||
|
||||
//// Removed for now.. See above brush and pen.
|
||||
// NtGdiSelectBrush(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
|
||||
// NtGdiSelectPen(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
|
||||
////
|
||||
//NtGdiSelectFont(DCHandle, hFont);
|
||||
|
||||
/*
|
||||
{
|
||||
int res;
|
||||
res = CLIPPING_UpdateGCRegion(DCToInit);
|
||||
ASSERT ( res != ERROR );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtGdiMakeInfoDC(
|
||||
IN HDC hdc,
|
||||
IN BOOL bSet)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HDC APIENTRY
|
||||
NtGdiCreateCompatibleDC(HDC hDC)
|
||||
{
|
||||
PDC NewDC, OrigDC;
|
||||
PDC_ATTR pdcattrNew, pdcattrOld;
|
||||
HDC hNewDC, DisplayDC = NULL;
|
||||
HRGN hVisRgn;
|
||||
UNICODE_STRING DriverName;
|
||||
DWORD Layout = 0;
|
||||
|
||||
if (hDC == NULL)
|
||||
{
|
||||
RtlInitUnicodeString(&DriverName, L"DISPLAY");
|
||||
DisplayDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, TRUE);
|
||||
if (NULL == DisplayDC)
|
||||
{
|
||||
DPRINT1("Failed to create DisplayDC\n");
|
||||
return NULL;
|
||||
}
|
||||
hDC = DisplayDC;
|
||||
}
|
||||
|
||||
/* Allocate a new DC based on the original DC's device */
|
||||
OrigDC = DC_LockDc(hDC);
|
||||
if (NULL == OrigDC)
|
||||
{
|
||||
if (NULL != DisplayDC)
|
||||
{
|
||||
NtGdiDeleteObjectApp(DisplayDC);
|
||||
}
|
||||
DPRINT1("Failed to lock hDC\n");
|
||||
return NULL;
|
||||
}
|
||||
hNewDC = DC_AllocDC(&OrigDC->rosdc.DriverName);
|
||||
if (NULL == hNewDC)
|
||||
{
|
||||
DPRINT1("Failed to create hNewDC\n");
|
||||
DC_UnlockDc(OrigDC);
|
||||
if (NULL != DisplayDC)
|
||||
{
|
||||
NtGdiDeleteObjectApp(DisplayDC);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
NewDC = DC_LockDc( hNewDC );
|
||||
|
||||
if(!NewDC)
|
||||
{
|
||||
DPRINT1("Failed to lock hNewDC\n");
|
||||
NtGdiDeleteObjectApp(hNewDC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdcattrOld = OrigDC->pdcattr;
|
||||
pdcattrNew = NewDC->pdcattr;
|
||||
|
||||
/* Copy information from original DC to new DC */
|
||||
NewDC->dclevel.hdcSave = hNewDC;
|
||||
|
||||
NewDC->dhpdev = OrigDC->dhpdev;
|
||||
|
||||
NewDC->rosdc.bitsPerPixel = OrigDC->rosdc.bitsPerPixel;
|
||||
|
||||
/* DriverName is copied in the AllocDC routine */
|
||||
pdcattrNew->ptlWindowOrg = pdcattrOld->ptlWindowOrg;
|
||||
pdcattrNew->szlWindowExt = pdcattrOld->szlWindowExt;
|
||||
pdcattrNew->ptlViewportOrg = pdcattrOld->ptlViewportOrg;
|
||||
pdcattrNew->szlViewportExt = pdcattrOld->szlViewportExt;
|
||||
|
||||
NewDC->dctype = DC_TYPE_MEMORY; // Always!
|
||||
NewDC->rosdc.hBitmap = NtGdiGetStockObject(DEFAULT_BITMAP);
|
||||
NewDC->ppdev = OrigDC->ppdev;
|
||||
NewDC->dclevel.hpal = OrigDC->dclevel.hpal;
|
||||
|
||||
pdcattrNew->lTextAlign = pdcattrOld->lTextAlign;
|
||||
pdcattrNew->lBkMode = pdcattrOld->lBkMode;
|
||||
pdcattrNew->jBkMode = pdcattrOld->jBkMode;
|
||||
pdcattrNew->jROP2 = pdcattrOld->jROP2;
|
||||
pdcattrNew->dwLayout = pdcattrOld->dwLayout;
|
||||
if (pdcattrOld->dwLayout & LAYOUT_ORIENTATIONMASK) Layout = pdcattrOld->dwLayout;
|
||||
NewDC->dclevel.flPath = OrigDC->dclevel.flPath;
|
||||
pdcattrNew->ulDirty_ = pdcattrOld->ulDirty_;
|
||||
pdcattrNew->iCS_CP = pdcattrOld->iCS_CP;
|
||||
|
||||
NewDC->erclWindow = (RECTL){0,0,1,1};
|
||||
|
||||
DC_UnlockDc(NewDC);
|
||||
DC_UnlockDc(OrigDC);
|
||||
if (NULL != DisplayDC)
|
||||
{
|
||||
NtGdiDeleteObjectApp(DisplayDC);
|
||||
}
|
||||
|
||||
hVisRgn = NtGdiCreateRectRgn(0, 0, 1, 1);
|
||||
if (hVisRgn)
|
||||
{
|
||||
GdiSelectVisRgn(hNewDC, hVisRgn);
|
||||
NtGdiDeleteObject(hVisRgn);
|
||||
}
|
||||
if (Layout) NtGdiSetLayout( hNewDC, -1, Layout);
|
||||
|
||||
DC_InitDC(hNewDC);
|
||||
return hNewDC;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtGdiDeleteObjectApp(HANDLE DCHandle)
|
||||
{
|
||||
/* Complete all pending operations */
|
||||
NtGdiFlushUserBatch();
|
||||
|
||||
if (GDI_HANDLE_IS_STOCKOBJ(DCHandle)) return TRUE;
|
||||
|
||||
if (GDI_HANDLE_GET_TYPE(DCHandle) != GDI_OBJECT_TYPE_DC)
|
||||
return NtGdiDeleteObject((HGDIOBJ) DCHandle);
|
||||
|
||||
if(IsObjectDead((HGDIOBJ)DCHandle)) return TRUE;
|
||||
|
||||
if (!GDIOBJ_OwnedByCurrentProcess(DCHandle))
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return IntGdiDeleteDC(DCHandle, FALSE);
|
||||
}
|
||||
|
281
reactos/subsystems/win32/win32k/objects/dcobjs.c
Normal file
281
reactos/subsystems/win32/win32k/objects/dcobjs.c
Normal file
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: Functions for creation and destruction of DCs
|
||||
* FILE: subsystem/win32/win32k/objects/dcobjs.c
|
||||
* PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
|
||||
*/
|
||||
|
||||
#include <w32k.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
DC_vUpdateFillBrush(PDC pdc)
|
||||
{
|
||||
PDC_ATTR pdcattr = pdc->pdcattr;
|
||||
PBRUSH pbrFill;
|
||||
XLATEOBJ *pxlo;
|
||||
ULONG iSolidColor;
|
||||
|
||||
/* Check if update of eboFill is needed */
|
||||
if (pdcattr->ulDirty_ & DIRTY_FILL)
|
||||
{
|
||||
/* ROS HACK, should use surf xlate */
|
||||
pxlo = pdc->rosdc.XlatePen;
|
||||
|
||||
/* Check if the brush handle has changed */
|
||||
if (pdcattr->hbrush != pdc->dclevel.pbrFill->BaseObject.hHmgr)
|
||||
{
|
||||
/* Try to lock the new brush */
|
||||
pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush);
|
||||
if (pbrFill)
|
||||
{
|
||||
/* Unlock old brush, set new brush */
|
||||
BRUSH_ShareUnlockBrush(pdc->dclevel.pbrFill);
|
||||
pdc->dclevel.pbrFill = pbrFill;
|
||||
|
||||
/* Update eboFill, realizing it, if needed */
|
||||
EBRUSHOBJ_vUpdate(&pdc->eboFill, pbrFill, pxlo);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid brush handle, restore old one */
|
||||
pdcattr->hbrush = pdc->dclevel.pbrFill->BaseObject.hHmgr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for DC brush */
|
||||
if (pdcattr->hbrush == StockObjects[DC_BRUSH])
|
||||
{
|
||||
/* Translate the color to the target format */
|
||||
iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crPenClr);
|
||||
|
||||
/* Update the eboFill's solid color */
|
||||
EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboFill, iSolidColor);
|
||||
}
|
||||
|
||||
/* Clear flag */
|
||||
pdcattr->ulDirty_ &= ~DIRTY_FILL;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
DC_vUpdateLineBrush(PDC pdc)
|
||||
{
|
||||
PDC_ATTR pdcattr = pdc->pdcattr;
|
||||
PBRUSH pbrLine;
|
||||
XLATEOBJ *pxlo;
|
||||
ULONG iSolidColor;
|
||||
|
||||
/* Check if update of eboLine is needed */
|
||||
if (pdcattr->ulDirty_ & DIRTY_LINE)
|
||||
{
|
||||
/* ROS HACK, should use surf xlate */
|
||||
pxlo = pdc->rosdc.XlatePen;
|
||||
|
||||
/* Check if the pen handle has changed */
|
||||
if (pdcattr->hpen != pdc->dclevel.pbrLine->BaseObject.hHmgr)
|
||||
{
|
||||
/* Try to lock the new pen */
|
||||
pbrLine = BRUSH_ShareLockBrush(pdcattr->hpen);
|
||||
if (pbrLine)
|
||||
{
|
||||
/* Unlock old brush, set new brush */
|
||||
BRUSH_ShareUnlockBrush(pdc->dclevel.pbrLine);
|
||||
pdc->dclevel.pbrLine = pbrLine;
|
||||
|
||||
/* Update eboLine, realizing it, if needed */
|
||||
EBRUSHOBJ_vUpdate(&pdc->eboLine, pbrLine, pxlo);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid pen handle, restore old one */
|
||||
pdcattr->hpen = pdc->dclevel.pbrLine->BaseObject.hHmgr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for DC pen */
|
||||
if (pdcattr->hpen == StockObjects[DC_PEN])
|
||||
{
|
||||
/* Translate the color to the target format */
|
||||
iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crPenClr);
|
||||
|
||||
/* Update the eboLine's solid color */
|
||||
EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboLine, iSolidColor);
|
||||
}
|
||||
|
||||
/* Clear flag */
|
||||
pdcattr->ulDirty_ &= ~DIRTY_LINE;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
DC_vUpdateTextBrush(PDC pdc)
|
||||
{
|
||||
PDC_ATTR pdcattr = pdc->pdcattr;
|
||||
XLATEOBJ *pxlo;
|
||||
ULONG iSolidColor;
|
||||
|
||||
/* Check if update of eboText is needed */
|
||||
if (pdcattr->ulDirty_ & DIRTY_TEXT)
|
||||
{
|
||||
/* ROS HACK, should use surf xlate */
|
||||
pxlo = pdc->rosdc.XlatePen;
|
||||
|
||||
/* Translate the color to the target format */
|
||||
iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crForegroundClr);
|
||||
|
||||
/* Update the eboText's solid color */
|
||||
EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboText, iSolidColor);
|
||||
|
||||
/* Clear flag */
|
||||
pdcattr->ulDirty_ &= ~DIRTY_TEXT;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
DC_vUpdateBackgroundBrush(PDC pdc)
|
||||
{
|
||||
PDC_ATTR pdcattr = pdc->pdcattr;
|
||||
XLATEOBJ *pxlo;
|
||||
ULONG iSolidColor;
|
||||
|
||||
/* Check if update of eboBackground is needed */
|
||||
if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
|
||||
{
|
||||
/* ROS HACK, should use surf xlate */
|
||||
pxlo = pdc->rosdc.XlatePen;
|
||||
|
||||
/* Translate the color to the target format */
|
||||
iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crBackgroundClr);
|
||||
|
||||
/* Update the eboBackground's solid color */
|
||||
EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboBackground, iSolidColor);
|
||||
|
||||
/* Clear flag */
|
||||
pdcattr->ulDirty_ &= ~DIRTY_BACKGROUND;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ULONG
|
||||
APIENTRY
|
||||
NtGdiEnumObjects(
|
||||
IN HDC hdc,
|
||||
IN INT iObjectType,
|
||||
IN ULONG cjBuf,
|
||||
OUT OPTIONAL PVOID pvBuf)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
HANDLE
|
||||
APIENTRY
|
||||
NtGdiGetDCObject(HDC hDC, INT ObjectType)
|
||||
{
|
||||
HGDIOBJ SelObject;
|
||||
DC *dc;
|
||||
PDC_ATTR pdcattr;
|
||||
|
||||
/* From Wine: GetCurrentObject does not SetLastError() on a null object */
|
||||
if(!hDC) return NULL;
|
||||
|
||||
if(!(dc = DC_LockDc(hDC)))
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return NULL;
|
||||
}
|
||||
pdcattr = dc->pdcattr;
|
||||
|
||||
if (pdcattr->ulDirty_ & DC_BRUSH_DIRTY)
|
||||
IntGdiSelectBrush(dc,pdcattr->hbrush);
|
||||
|
||||
if (pdcattr->ulDirty_ & DC_PEN_DIRTY)
|
||||
IntGdiSelectPen(dc,pdcattr->hpen);
|
||||
|
||||
switch(ObjectType)
|
||||
{
|
||||
case GDI_OBJECT_TYPE_EXTPEN:
|
||||
case GDI_OBJECT_TYPE_PEN:
|
||||
SelObject = pdcattr->hpen;
|
||||
break;
|
||||
case GDI_OBJECT_TYPE_BRUSH:
|
||||
SelObject = pdcattr->hbrush;
|
||||
break;
|
||||
case GDI_OBJECT_TYPE_PALETTE:
|
||||
SelObject = dc->dclevel.hpal;
|
||||
break;
|
||||
case GDI_OBJECT_TYPE_FONT:
|
||||
SelObject = pdcattr->hlfntNew;
|
||||
break;
|
||||
case GDI_OBJECT_TYPE_BITMAP:
|
||||
SelObject = dc->rosdc.hBitmap;
|
||||
break;
|
||||
case GDI_OBJECT_TYPE_COLORSPACE:
|
||||
DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
|
||||
// SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ?
|
||||
SelObject = NULL;
|
||||
break;
|
||||
default:
|
||||
SelObject = NULL;
|
||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||
break;
|
||||
}
|
||||
|
||||
DC_UnlockDc(dc);
|
||||
return SelObject;
|
||||
}
|
||||
|
||||
HPALETTE
|
||||
FASTCALL
|
||||
GdiSelectPalette(HDC hDC,
|
||||
HPALETTE hpal,
|
||||
BOOL ForceBackground)
|
||||
{
|
||||
PDC dc;
|
||||
HPALETTE oldPal = NULL;
|
||||
PPALGDI PalGDI;
|
||||
|
||||
// FIXME: mark the palette as a [fore\back]ground pal
|
||||
dc = DC_LockDc(hDC);
|
||||
if (!dc)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if this is a valid palette handle */
|
||||
PalGDI = PALETTE_LockPalette(hpal);
|
||||
if (!PalGDI)
|
||||
{
|
||||
DC_UnlockDc(dc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Is this a valid palette for this depth? */
|
||||
if ((dc->rosdc.bitsPerPixel <= 8 && PalGDI->Mode == PAL_INDEXED) ||
|
||||
(dc->rosdc.bitsPerPixel > 8 && PalGDI->Mode != PAL_INDEXED))
|
||||
{
|
||||
oldPal = dc->dclevel.hpal;
|
||||
dc->dclevel.hpal = hpal;
|
||||
}
|
||||
else if (8 < dc->rosdc.bitsPerPixel && PAL_INDEXED == PalGDI->Mode)
|
||||
{
|
||||
oldPal = dc->dclevel.hpal;
|
||||
dc->dclevel.hpal = hpal;
|
||||
}
|
||||
|
||||
PALETTE_UnlockPalette(PalGDI);
|
||||
DC_UnlockDc(dc);
|
||||
|
||||
return oldPal;
|
||||
}
|
384
reactos/subsystems/win32/win32k/objects/dcstate.c
Normal file
384
reactos/subsystems/win32/win32k/objects/dcstate.c
Normal file
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: Functions for creation and destruction of DCs
|
||||
* FILE: subsystem/win32/win32k/objects/dcstate.c
|
||||
* PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
|
||||
*/
|
||||
|
||||
#include <w32k.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
IntGdiCopyToSaveState(PDC dc, PDC newdc)
|
||||
{
|
||||
PDC_ATTR pdcattr, nDc_Attr;
|
||||
|
||||
pdcattr = dc->pdcattr;
|
||||
nDc_Attr = newdc->pdcattr;
|
||||
|
||||
newdc->dclevel.flPath = dc->dclevel.flPath | DCPATH_SAVESTATE;
|
||||
|
||||
nDc_Attr->dwLayout = pdcattr->dwLayout;
|
||||
nDc_Attr->hpen = pdcattr->hpen;
|
||||
nDc_Attr->hbrush = pdcattr->hbrush;
|
||||
nDc_Attr->hlfntNew = pdcattr->hlfntNew;
|
||||
newdc->rosdc.hBitmap = dc->rosdc.hBitmap;
|
||||
newdc->dclevel.hpal = dc->dclevel.hpal;
|
||||
newdc->rosdc.bitsPerPixel = dc->rosdc.bitsPerPixel;
|
||||
nDc_Attr->jROP2 = pdcattr->jROP2;
|
||||
nDc_Attr->jFillMode = pdcattr->jFillMode;
|
||||
nDc_Attr->jStretchBltMode = pdcattr->jStretchBltMode;
|
||||
nDc_Attr->lRelAbs = pdcattr->lRelAbs;
|
||||
nDc_Attr->jBkMode = pdcattr->jBkMode;
|
||||
nDc_Attr->lBkMode = pdcattr->lBkMode;
|
||||
nDc_Attr->crBackgroundClr = pdcattr->crBackgroundClr;
|
||||
nDc_Attr->crForegroundClr = pdcattr->crForegroundClr;
|
||||
nDc_Attr->ulBackgroundClr = pdcattr->ulBackgroundClr;
|
||||
nDc_Attr->ulForegroundClr = pdcattr->ulForegroundClr;
|
||||
nDc_Attr->ptlBrushOrigin = pdcattr->ptlBrushOrigin;
|
||||
nDc_Attr->lTextAlign = pdcattr->lTextAlign;
|
||||
nDc_Attr->lTextExtra = pdcattr->lTextExtra;
|
||||
nDc_Attr->cBreak = pdcattr->cBreak;
|
||||
nDc_Attr->lBreakExtra = pdcattr->lBreakExtra;
|
||||
nDc_Attr->iMapMode = pdcattr->iMapMode;
|
||||
nDc_Attr->iGraphicsMode = pdcattr->iGraphicsMode;
|
||||
#if 0
|
||||
/* Apparently, the DC origin is not changed by [GS]etDCState */
|
||||
newdc->ptlDCOrig.x = dc->ptlDCOrig.x;
|
||||
newdc->ptlDCOrig.y = dc->ptlDCOrig.y;
|
||||
#endif
|
||||
nDc_Attr->ptlCurrent = pdcattr->ptlCurrent;
|
||||
nDc_Attr->ptfxCurrent = pdcattr->ptfxCurrent;
|
||||
newdc->dclevel.mxWorldToDevice = dc->dclevel.mxWorldToDevice;
|
||||
newdc->dclevel.mxDeviceToWorld = dc->dclevel.mxDeviceToWorld;
|
||||
newdc->dclevel.mxWorldToPage = dc->dclevel.mxWorldToPage;
|
||||
nDc_Attr->flXform = pdcattr->flXform;
|
||||
nDc_Attr->ptlWindowOrg = pdcattr->ptlWindowOrg;
|
||||
nDc_Attr->szlWindowExt = pdcattr->szlWindowExt;
|
||||
nDc_Attr->ptlViewportOrg = pdcattr->ptlViewportOrg;
|
||||
nDc_Attr->szlViewportExt = pdcattr->szlViewportExt;
|
||||
|
||||
newdc->dclevel.lSaveDepth = 0;
|
||||
newdc->dctype = dc->dctype;
|
||||
|
||||
#if 0
|
||||
PATH_InitGdiPath( &newdc->dclevel.hPath );
|
||||
#endif
|
||||
|
||||
/* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
|
||||
|
||||
newdc->rosdc.hGCClipRgn = newdc->rosdc.hVisRgn = 0;
|
||||
if (dc->rosdc.hClipRgn)
|
||||
{
|
||||
newdc->rosdc.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
|
||||
NtGdiCombineRgn( newdc->rosdc.hClipRgn, dc->rosdc.hClipRgn, 0, RGN_COPY );
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: why 2 different functions that do the same?
|
||||
VOID
|
||||
FASTCALL
|
||||
IntGdiCopyFromSaveState(PDC dc, PDC dcs, HDC hDC)
|
||||
{
|
||||
PDC_ATTR pdcattr, sDc_Attr;
|
||||
|
||||
pdcattr = dc->pdcattr;
|
||||
sDc_Attr = dcs->pdcattr;
|
||||
|
||||
dc->dclevel.flPath = dcs->dclevel.flPath & ~DCPATH_SAVESTATE;
|
||||
|
||||
pdcattr->dwLayout = sDc_Attr->dwLayout;
|
||||
pdcattr->jROP2 = sDc_Attr->jROP2;
|
||||
pdcattr->jFillMode = sDc_Attr->jFillMode;
|
||||
pdcattr->jStretchBltMode = sDc_Attr->jStretchBltMode;
|
||||
pdcattr->lRelAbs = sDc_Attr->lRelAbs;
|
||||
pdcattr->jBkMode = sDc_Attr->jBkMode;
|
||||
pdcattr->crBackgroundClr = sDc_Attr->crBackgroundClr;
|
||||
pdcattr->crForegroundClr = sDc_Attr->crForegroundClr;
|
||||
pdcattr->lBkMode = sDc_Attr->lBkMode;
|
||||
pdcattr->ulBackgroundClr = sDc_Attr->ulBackgroundClr;
|
||||
pdcattr->ulForegroundClr = sDc_Attr->ulForegroundClr;
|
||||
pdcattr->ptlBrushOrigin = sDc_Attr->ptlBrushOrigin;
|
||||
|
||||
pdcattr->lTextAlign = sDc_Attr->lTextAlign;
|
||||
pdcattr->lTextExtra = sDc_Attr->lTextExtra;
|
||||
pdcattr->cBreak = sDc_Attr->cBreak;
|
||||
pdcattr->lBreakExtra = sDc_Attr->lBreakExtra;
|
||||
pdcattr->iMapMode = sDc_Attr->iMapMode;
|
||||
pdcattr->iGraphicsMode = sDc_Attr->iGraphicsMode;
|
||||
#if 0
|
||||
/* Apparently, the DC origin is not changed by [GS]etDCState */
|
||||
dc->ptlDCOrig.x = dcs->ptlDCOrig.x;
|
||||
dc->ptlDCOrig.y = dcs->ptlDCOrig.y;
|
||||
#endif
|
||||
pdcattr->ptlCurrent = sDc_Attr->ptlCurrent;
|
||||
pdcattr->ptfxCurrent = sDc_Attr->ptfxCurrent;
|
||||
dc->dclevel.mxWorldToDevice = dcs->dclevel.mxWorldToDevice;
|
||||
dc->dclevel.mxDeviceToWorld = dcs->dclevel.mxDeviceToWorld;
|
||||
dc->dclevel.mxWorldToPage = dcs->dclevel.mxWorldToPage;
|
||||
pdcattr->flXform = sDc_Attr->flXform;
|
||||
pdcattr->ptlWindowOrg = sDc_Attr->ptlWindowOrg;
|
||||
pdcattr->szlWindowExt = sDc_Attr->szlWindowExt;
|
||||
pdcattr->ptlViewportOrg = sDc_Attr->ptlViewportOrg;
|
||||
pdcattr->szlViewportExt = sDc_Attr->szlViewportExt;
|
||||
|
||||
if (dc->dctype != DC_TYPE_MEMORY)
|
||||
{
|
||||
dc->rosdc.bitsPerPixel = dcs->rosdc.bitsPerPixel;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (dcs->rosdc.hClipRgn)
|
||||
{
|
||||
if (!dc->rosdc.hClipRgn)
|
||||
{
|
||||
dc->rosdc.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
|
||||
}
|
||||
NtGdiCombineRgn( dc->rosdc.hClipRgn, dcs->rosdc.hClipRgn, 0, RGN_COPY );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dc->rosdc.hClipRgn)
|
||||
{
|
||||
NtGdiDeleteObject( dc->rosdc.hClipRgn );
|
||||
}
|
||||
dc->rosdc.hClipRgn = 0;
|
||||
}
|
||||
{
|
||||
int res;
|
||||
res = CLIPPING_UpdateGCRegion( dc );
|
||||
ASSERT ( res != ERROR );
|
||||
}
|
||||
DC_UnlockDc ( dc );
|
||||
#else
|
||||
GdiExtSelectClipRgn(dc, dcs->rosdc.hClipRgn, RGN_COPY);
|
||||
DC_UnlockDc ( dc );
|
||||
#endif
|
||||
if(!hDC) return; // Not a MemoryDC or SaveLevel DC, return.
|
||||
|
||||
NtGdiSelectBitmap( hDC, dcs->rosdc.hBitmap );
|
||||
NtGdiSelectBrush( hDC, sDc_Attr->hbrush );
|
||||
NtGdiSelectFont( hDC, sDc_Attr->hlfntNew );
|
||||
NtGdiSelectPen( hDC, sDc_Attr->hpen );
|
||||
|
||||
IntGdiSetBkColor( hDC, sDc_Attr->crBackgroundClr);
|
||||
IntGdiSetTextColor( hDC, sDc_Attr->crForegroundClr);
|
||||
|
||||
GdiSelectPalette( hDC, dcs->dclevel.hpal, FALSE );
|
||||
|
||||
#if 0
|
||||
GDISelectPalette16( hDC, dcs->dclevel.hpal, FALSE );
|
||||
#endif
|
||||
}
|
||||
|
||||
HDC APIENTRY
|
||||
IntGdiGetDCState(HDC hDC)
|
||||
{
|
||||
PDC newdc, dc;
|
||||
HDC hnewdc;
|
||||
|
||||
dc = DC_LockDc(hDC);
|
||||
if (dc == NULL)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
hnewdc = DC_AllocDC(NULL);
|
||||
if (hnewdc == NULL)
|
||||
{
|
||||
DC_UnlockDc(dc);
|
||||
return 0;
|
||||
}
|
||||
newdc = DC_LockDc( hnewdc );
|
||||
/* FIXME - newdc can be NULL!!!! Don't assert here!!! */
|
||||
ASSERT( newdc );
|
||||
|
||||
newdc->dclevel.hdcSave = hnewdc;
|
||||
IntGdiCopyToSaveState( dc, newdc);
|
||||
|
||||
DC_UnlockDc( newdc );
|
||||
DC_UnlockDc( dc );
|
||||
return hnewdc;
|
||||
}
|
||||
|
||||
VOID
|
||||
APIENTRY
|
||||
IntGdiSetDCState ( HDC hDC, HDC hDCSave )
|
||||
{
|
||||
PDC dc, dcs;
|
||||
|
||||
dc = DC_LockDc ( hDC );
|
||||
if ( dc )
|
||||
{
|
||||
dcs = DC_LockDc ( hDCSave );
|
||||
if ( dcs )
|
||||
{
|
||||
if ( dcs->dclevel.flPath & DCPATH_SAVESTATE )
|
||||
{
|
||||
IntGdiCopyFromSaveState( dc, dcs, dc->dclevel.hdcSave);
|
||||
}
|
||||
else
|
||||
{
|
||||
DC_UnlockDc(dc);
|
||||
}
|
||||
DC_UnlockDc ( dcs );
|
||||
}
|
||||
else
|
||||
{
|
||||
DC_UnlockDc ( dc );
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
}
|
||||
}
|
||||
else
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtGdiResetDC(
|
||||
IN HDC hdc,
|
||||
IN LPDEVMODEW pdm,
|
||||
OUT PBOOL pbBanding,
|
||||
IN OPTIONAL VOID *pDriverInfo2,
|
||||
OUT VOID *ppUMdhpdev)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL APIENTRY
|
||||
NtGdiRestoreDC(HDC hDC, INT SaveLevel)
|
||||
{
|
||||
PDC dc, dcs;
|
||||
BOOL success;
|
||||
|
||||
DPRINT("NtGdiRestoreDC(%lx, %d)\n", hDC, SaveLevel);
|
||||
|
||||
dc = DC_LockDc(hDC);
|
||||
if (!dc)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (SaveLevel < 0)
|
||||
SaveLevel = dc->dclevel.lSaveDepth + SaveLevel + 1;
|
||||
|
||||
if(SaveLevel < 0 || dc->dclevel.lSaveDepth<SaveLevel)
|
||||
{
|
||||
DC_UnlockDc(dc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
success=TRUE;
|
||||
while (dc->dclevel.lSaveDepth >= SaveLevel)
|
||||
{
|
||||
HDC hdcs = DC_GetNextDC (dc);
|
||||
|
||||
dcs = DC_LockDc (hdcs);
|
||||
if (dcs == NULL)
|
||||
{
|
||||
DC_UnlockDc(dc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DC_SetNextDC (dc, DC_GetNextDC (dcs));
|
||||
dcs->hdcNext = 0;
|
||||
|
||||
if (--dc->dclevel.lSaveDepth < SaveLevel)
|
||||
{
|
||||
DC_UnlockDc( dc );
|
||||
DC_UnlockDc( dcs );
|
||||
|
||||
IntGdiSetDCState(hDC, hdcs);
|
||||
|
||||
dc = DC_LockDc(hDC);
|
||||
if(!dc)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
// Restore Path by removing it, if the Save flag is set.
|
||||
// BeginPath will takecare of the rest.
|
||||
if ( dc->dclevel.hPath && dc->dclevel.flPath & DCPATH_SAVE)
|
||||
{
|
||||
PATH_Delete(dc->dclevel.hPath);
|
||||
dc->dclevel.hPath = 0;
|
||||
dc->dclevel.flPath &= ~DCPATH_SAVE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DC_UnlockDc( dcs );
|
||||
}
|
||||
NtGdiDeleteObjectApp (hdcs);
|
||||
}
|
||||
DC_UnlockDc( dc );
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
INT APIENTRY
|
||||
NtGdiSaveDC(HDC hDC)
|
||||
{
|
||||
HDC hdcs;
|
||||
PDC dc, dcs;
|
||||
INT ret;
|
||||
|
||||
DPRINT("NtGdiSaveDC(%lx)\n", hDC);
|
||||
|
||||
if (!(hdcs = IntGdiGetDCState(hDC)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
dcs = DC_LockDc (hdcs);
|
||||
if (dcs == NULL)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return 0;
|
||||
}
|
||||
dc = DC_LockDc (hDC);
|
||||
if (dc == NULL)
|
||||
{
|
||||
DC_UnlockDc(dcs);
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy path.
|
||||
*/
|
||||
dcs->dclevel.hPath = dc->dclevel.hPath;
|
||||
if (dcs->dclevel.hPath) dcs->dclevel.flPath |= DCPATH_SAVE;
|
||||
|
||||
DC_SetNextDC (dcs, DC_GetNextDC (dc));
|
||||
DC_SetNextDC (dc, hdcs);
|
||||
ret = ++dc->dclevel.lSaveDepth;
|
||||
DC_UnlockDc( dcs );
|
||||
DC_UnlockDc( dc );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOL FASTCALL
|
||||
IntGdiCleanDC(HDC hDC)
|
||||
{
|
||||
PDC dc;
|
||||
if (!hDC) return FALSE;
|
||||
dc = DC_LockDc ( hDC );
|
||||
if (!dc) return FALSE;
|
||||
// Clean the DC
|
||||
if (defaultDCstate) IntGdiCopyFromSaveState(dc, defaultDCstate, hDC );
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -105,58 +105,6 @@ INT APIENTRY func_name( HDC hdc, INT mode ) \
|
|||
}
|
||||
|
||||
|
||||
static
|
||||
VOID
|
||||
CopytoUserDcAttr(PDC dc, PDC_ATTR pdcattr)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
dc->dcattr.mxWorldToDevice = dc->dclevel.mxWorldToDevice;
|
||||
dc->dcattr.mxDeviceToWorld = dc->dclevel.mxDeviceToWorld;
|
||||
dc->dcattr.mxWorldToPage = dc->dclevel.mxWorldToPage;
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForWrite( pdcattr,
|
||||
sizeof(DC_ATTR),
|
||||
1);
|
||||
RtlCopyMemory( pdcattr,
|
||||
&dc->dcattr,
|
||||
sizeof(DC_ATTR));
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
DCU_SyncDcAttrtoUser(PDC dc)
|
||||
{
|
||||
PDC_ATTR pdcattr = dc->pdcattr;
|
||||
|
||||
if (pdcattr == &dc->dcattr) return TRUE; // No need to copy self.
|
||||
ASSERT(pdcattr);
|
||||
CopytoUserDcAttr( dc, pdcattr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
DCU_SynchDcAttrtoUser(HDC hDC)
|
||||
{
|
||||
BOOL Ret;
|
||||
PDC pDC = DC_LockDc ( hDC );
|
||||
if (!pDC) return FALSE;
|
||||
Ret = DCU_SyncDcAttrtoUser(pDC);
|
||||
DC_UnlockDc( pDC );
|
||||
return Ret;
|
||||
}
|
||||
|
||||
|
||||
DC_GET_VAL( INT, IntGdiGetMapMode, iMapMode )
|
||||
DC_GET_VAL( INT, IntGdiGetPolyFillMode, jFillMode )
|
||||
DC_GET_VAL( COLORREF, IntGdiGetBkColor, crBackgroundClr )
|
||||
|
@ -283,3 +231,293 @@ DCU_SetDcUndeletable(HDC hDC)
|
|||
DC_UnlockDc( dc );
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
BOOL FASTCALL
|
||||
IntIsPrimarySurface(SURFOBJ *SurfObj)
|
||||
{
|
||||
if (PrimarySurface.pSurface == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return SurfObj->hsurf == PrimarySurface.pSurface; // <- FIXME: WTF?
|
||||
}
|
||||
#endif
|
||||
|
||||
// FIXME: remove me
|
||||
HDC FASTCALL
|
||||
DC_GetNextDC (PDC pDC)
|
||||
{
|
||||
return pDC->hdcNext;
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
DC_SetNextDC (PDC pDC, HDC hNextDC)
|
||||
{
|
||||
pDC->hdcNext = hNextDC;
|
||||
}
|
||||
|
||||
|
||||
BOOL APIENTRY
|
||||
NtGdiCancelDC(HDC hDC)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
WORD APIENTRY
|
||||
IntGdiSetHookFlags(HDC hDC, WORD Flags)
|
||||
{
|
||||
WORD wRet;
|
||||
DC *dc = DC_LockDc(hDC);
|
||||
|
||||
if (NULL == dc)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wRet = dc->fs & DC_FLAG_DIRTY_RAO; // Fixme wrong flag!
|
||||
|
||||
/* "Undocumented Windows" info is slightly confusing.
|
||||
*/
|
||||
|
||||
DPRINT("DC %p, Flags %04x\n", hDC, Flags);
|
||||
|
||||
if (Flags & DCHF_INVALIDATEVISRGN)
|
||||
{ /* hVisRgn has to be updated */
|
||||
dc->fs |= DC_FLAG_DIRTY_RAO;
|
||||
}
|
||||
else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags)
|
||||
{
|
||||
dc->fs &= ~DC_FLAG_DIRTY_RAO;
|
||||
}
|
||||
|
||||
DC_UnlockDc(dc);
|
||||
|
||||
return wRet;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtGdiGetDCDword(
|
||||
HDC hDC,
|
||||
UINT u,
|
||||
DWORD *Result
|
||||
)
|
||||
{
|
||||
BOOL Ret = TRUE;
|
||||
PDC dc;
|
||||
PDC_ATTR pdcattr;
|
||||
|
||||
DWORD SafeResult = 0;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
if(!Result)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dc = DC_LockDc(hDC);
|
||||
if(!dc)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
pdcattr = dc->pdcattr;
|
||||
|
||||
switch (u)
|
||||
{
|
||||
case GdiGetJournal:
|
||||
break;
|
||||
case GdiGetRelAbs:
|
||||
SafeResult = pdcattr->lRelAbs;
|
||||
break;
|
||||
case GdiGetBreakExtra:
|
||||
SafeResult = pdcattr->lBreakExtra;
|
||||
break;
|
||||
case GdiGerCharBreak:
|
||||
SafeResult = pdcattr->cBreak;
|
||||
break;
|
||||
case GdiGetArcDirection:
|
||||
if (pdcattr->dwLayout & LAYOUT_RTL)
|
||||
SafeResult = AD_CLOCKWISE - ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
|
||||
else
|
||||
SafeResult = ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) + AD_COUNTERCLOCKWISE;
|
||||
break;
|
||||
case GdiGetEMFRestorDc:
|
||||
break;
|
||||
case GdiGetFontLanguageInfo:
|
||||
SafeResult = IntGetFontLanguageInfo(dc);
|
||||
break;
|
||||
case GdiGetIsMemDc:
|
||||
SafeResult = dc->dctype;
|
||||
break;
|
||||
case GdiGetMapMode:
|
||||
SafeResult = pdcattr->iMapMode;
|
||||
break;
|
||||
case GdiGetTextCharExtra:
|
||||
SafeResult = pdcattr->lTextExtra;
|
||||
break;
|
||||
default:
|
||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||
Ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Ret)
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForWrite(Result,
|
||||
sizeof(DWORD),
|
||||
1);
|
||||
*Result = SafeResult;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastNtError(Status);
|
||||
DC_UnlockDc(dc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DC_UnlockDc(dc);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtGdiGetAndSetDCDword(
|
||||
HDC hDC,
|
||||
UINT u,
|
||||
DWORD dwIn,
|
||||
DWORD *Result
|
||||
)
|
||||
{
|
||||
BOOL Ret = TRUE;
|
||||
PDC dc;
|
||||
PDC_ATTR pdcattr;
|
||||
|
||||
DWORD SafeResult = 0;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
if(!Result)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dc = DC_LockDc(hDC);
|
||||
if(!dc)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
pdcattr = dc->pdcattr;
|
||||
|
||||
switch (u)
|
||||
{
|
||||
case GdiGetSetCopyCount:
|
||||
SafeResult = dc->ulCopyCount;
|
||||
dc->ulCopyCount = dwIn;
|
||||
break;
|
||||
case GdiGetSetTextAlign:
|
||||
SafeResult = pdcattr->lTextAlign;
|
||||
pdcattr->lTextAlign = dwIn;
|
||||
// pdcattr->flTextAlign = dwIn; // Flags!
|
||||
break;
|
||||
case GdiGetSetRelAbs:
|
||||
SafeResult = pdcattr->lRelAbs;
|
||||
pdcattr->lRelAbs = dwIn;
|
||||
break;
|
||||
case GdiGetSetTextCharExtra:
|
||||
SafeResult = pdcattr->lTextExtra;
|
||||
pdcattr->lTextExtra = dwIn;
|
||||
break;
|
||||
case GdiGetSetSelectFont:
|
||||
break;
|
||||
case GdiGetSetMapperFlagsInternal:
|
||||
if (dwIn & ~1)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||
Ret = FALSE;
|
||||
break;
|
||||
}
|
||||
SafeResult = pdcattr->flFontMapper;
|
||||
pdcattr->flFontMapper = dwIn;
|
||||
break;
|
||||
case GdiGetSetMapMode:
|
||||
SafeResult = IntGdiSetMapMode( dc, dwIn);
|
||||
break;
|
||||
case GdiGetSetArcDirection:
|
||||
if (dwIn != AD_COUNTERCLOCKWISE && dwIn != AD_CLOCKWISE)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||
Ret = FALSE;
|
||||
break;
|
||||
}
|
||||
if ( pdcattr->dwLayout & LAYOUT_RTL ) // Right to Left
|
||||
{
|
||||
SafeResult = AD_CLOCKWISE - ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
|
||||
if ( dwIn == AD_CLOCKWISE )
|
||||
{
|
||||
dc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
|
||||
break;
|
||||
}
|
||||
dc->dclevel.flPath |= DCPATH_CLOCKWISE;
|
||||
}
|
||||
else // Left to Right
|
||||
{
|
||||
SafeResult = ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) + AD_COUNTERCLOCKWISE;
|
||||
if ( dwIn == AD_COUNTERCLOCKWISE)
|
||||
{
|
||||
dc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
|
||||
break;
|
||||
}
|
||||
dc->dclevel.flPath |= DCPATH_CLOCKWISE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||
Ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Ret)
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForWrite(Result,
|
||||
sizeof(DWORD),
|
||||
1);
|
||||
*Result = SafeResult;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastNtError(Status);
|
||||
DC_UnlockDc(dc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DC_UnlockDc(dc);
|
||||
return Ret;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -160,8 +160,12 @@
|
|||
<file>cliprgn.c</file>
|
||||
<file>color.c</file>
|
||||
<file>coord.c</file>
|
||||
<file>dc.c</file>
|
||||
<file>dcattr.c</file>
|
||||
<file>dclife.c</file>
|
||||
<file>dcobjs.c</file>
|
||||
<file>dcstate.c</file>
|
||||
<file>dcutil.c</file>
|
||||
<file>device.c</file>
|
||||
<file>dibobj.c</file>
|
||||
<file>drawing.c</file>
|
||||
<file>fillshap.c</file>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue