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:
Timo Kreuzer 2009-03-23 03:43:11 +00:00
parent 8cb1d37567
commit d7ab2a464e
9 changed files with 2467 additions and 2399 deletions

View file

@ -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 */

View file

@ -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 */

View 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;
}

View 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);
}

View 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;
}

View 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;
}

View file

@ -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;
}

View file

@ -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>