Author: tkreuzer
Date: Wed Mar 25 07:20:59 2009
New Revision: 40219
URL:
http://svn.reactos.org/svn/reactos?rev=40219&view=rev
Log:
Rewrite the dc state saving implementation. We were doing it wrong and ugly. Now it should
work correctly. It's also much fewer and cleaner code.
Modified:
trunk/reactos/subsystems/win32/win32k/include/dc.h
trunk/reactos/subsystems/win32/win32k/ntuser/windc.c
trunk/reactos/subsystems/win32/win32k/objects/dclife.c
trunk/reactos/subsystems/win32/win32k/objects/dcstate.c
Modified: trunk/reactos/subsystems/win32/win32k/include/dc.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/in…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/dc.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/include/dc.h [iso-8859-1] Wed Mar 25 07:20:59
2009
@@ -237,18 +237,15 @@
VOID FASTCALL DC_AllocateDcAttr(HDC);
VOID FASTCALL DC_FreeDcAttr(HDC);
BOOL INTERNAL_CALL DC_Cleanup(PVOID ObjectBody);
-HDC FASTCALL DC_GetNextDC (PDC pDC);
-VOID FASTCALL DC_SetNextDC (PDC pDC, HDC hNextDC);
BOOL FASTCALL DC_SetOwnership(HDC DC, PEPROCESS Owner);
VOID FASTCALL DC_LockDisplay(HDC);
VOID FASTCALL DC_UnlockDisplay(HDC);
-VOID FASTCALL IntGdiCopyFromSaveState(PDC, PDC, HDC);
-VOID FASTCALL IntGdiCopyToSaveState(PDC, PDC);
BOOL FASTCALL IntGdiDeleteDC(HDC, BOOL);
VOID FASTCALL DC_UpdateXforms(PDC dc);
BOOL FASTCALL DC_InvertXform(const XFORM *xformSrc, XFORM *xformDest);
VOID FASTCALL DC_vUpdateViewportExt(PDC pdc);
+VOID FASTCALL DC_vCopyState(PDC pdcSrc, PDC pdcDst);
BOOL FASTCALL DCU_SyncDcAttrtoUser(PDC);
BOOL FASTCALL DCU_SynchDcAttrtoUser(HDC);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/windc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/windc.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/windc.c [iso-8859-1] Wed Mar 25 07:20:59
2009
@@ -2,7 +2,7 @@
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: subsystems/win32/win32k/ntuser/windc.c
- * PURPOSE: Keyboard layout management
+ * PURPOSE: Window DC management
* COPYRIGHT: Copyright 2007 ReactOS
*
*/
@@ -45,7 +45,7 @@
defaultDCstate = ExAllocatePoolWithTag(PagedPool, sizeof(DC), TAG_DC);
RtlZeroMemory(defaultDCstate, sizeof(DC));
defaultDCstate->pdcattr = &defaultDCstate->dcattr;
- IntGdiCopyToSaveState(dc, defaultDCstate);
+ DC_vCopyState(dc, defaultDCstate);
DC_UnlockDc( dc );
}
return hDC;
Modified: trunk/reactos/subsystems/win32/win32k/objects/dclife.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/dclife.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/dclife.c [iso-8859-1] Wed Mar 25
07:20:59 2009
@@ -112,6 +112,8 @@
NewDC->dclevel.hpal = NtGdiGetStockObject(DEFAULT_PALETTE);
NewDC->dclevel.laPath.eMiterLimit = 10.0;
+
+ NewDC->dclevel.lSaveDepth = 1;
return NewDC;
}
@@ -419,7 +421,7 @@
}
RtlZeroMemory(defaultDCstate, sizeof(DC));
defaultDCstate->pdcattr = &defaultDCstate->dcattr;
- IntGdiCopyToSaveState(dc, defaultDCstate);
+ DC_vCopyState(dc, defaultDCstate);
DC_UnlockDc(dc);
}
return hDC;
@@ -448,7 +450,7 @@
}
/* First delete all saved DCs */
- while (DCToDelete->dclevel.lSaveDepth)
+ while (DCToDelete->dclevel.lSaveDepth > 1)
{
PDC savedDC;
HDC savedHDC;
Modified: trunk/reactos/subsystems/win32/win32k/objects/dcstate.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/dcstate.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/dcstate.c [iso-8859-1] Wed Mar 25
07:20:59 2009
@@ -11,231 +11,73 @@
#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
+DC_vCopyState(PDC pdcSrc, PDC pdcDst)
+{
+ /* Copy full DC attribute */
+ *pdcDst->pdcattr = *pdcSrc->pdcattr;
/* 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;
+ /* The VisRectRegion field needs to be set to a valid state */
+
+ /* Mark some fields as dirty */
+ pdcDst->pdcattr->ulDirty_ |= 0x0012001f;
+
+ /* Copy DC level */
+ pdcDst->dclevel.pColorSpace = pdcSrc->dclevel.pColorSpace;
+ pdcDst->dclevel.lSaveDepth = pdcSrc->dclevel.lSaveDepth;
+ pdcDst->dclevel.hdcSave = pdcSrc->dclevel.hdcSave;
+ pdcDst->dclevel.laPath = pdcSrc->dclevel.laPath;
+ pdcDst->dclevel.ca = pdcSrc->dclevel.ca;
+ pdcDst->dclevel.mxWorldToDevice = pdcSrc->dclevel.mxWorldToDevice;
+ pdcDst->dclevel.mxDeviceToWorld = pdcSrc->dclevel.mxDeviceToWorld;
+ pdcDst->dclevel.mxWorldToPage = pdcSrc->dclevel.mxWorldToPage;
+ pdcDst->dclevel.efM11PtoD = pdcSrc->dclevel.efM11PtoD;
+ pdcDst->dclevel.efM22PtoD = pdcSrc->dclevel.efM22PtoD;
+ pdcDst->dclevel.sizl = pdcSrc->dclevel.sizl;
+
+ /* Handle references here correctly */
+ DC_vSelectSurface(pdcDst, pdcSrc->dclevel.pSurface);
+
+ // FIXME: handle refs
+ pdcDst->dclevel.hpal = pdcSrc->dclevel.hpal;
+ pdcDst->dclevel.ppal = pdcSrc->dclevel.ppal;
+ pdcDst->dclevel.pbrFill = pdcSrc->dclevel.pbrFill;
+ pdcDst->dclevel.pbrLine = pdcSrc->dclevel.pbrLine;
+ pdcDst->dclevel.plfnt = pdcSrc->dclevel.plfnt;
+
+ /* ROS hacks */
+ pdcDst->rosdc.hBitmap = pdcSrc->rosdc.hBitmap;
+
+ if (pdcDst->dctype != DC_TYPE_MEMORY)
+ {
+ pdcDst->rosdc.bitsPerPixel = pdcSrc->rosdc.bitsPerPixel;
+ }
+
+ GdiExtSelectClipRgn(pdcDst, pdcSrc->rosdc.hClipRgn, RGN_COPY);
+
+}
+
+
+BOOL FASTCALL
+IntGdiCleanDC(HDC hDC)
+{
+ PDC dc;
+ if (!hDC) return FALSE;
+ dc = DC_LockDc(hDC);
+ if (!dc) return FALSE;
+ // Clean the DC
+ if (defaultDCstate) DC_vCopyState(defaultDCstate, dc);
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->rosdc.bitsPerPixel = defaultDCstate->rosdc.bitsPerPixel;
+ }
+
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 pdcNew, pdc;
- HDC hdcNew;
-
- pdc = DC_LockDc(hDC);
- if (pdc == NULL)
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return 0;
- }
-
- pdcNew = DC_AllocDC(NULL);
- if (pdcNew == NULL)
- {
- DC_UnlockDc(pdc);
- return 0;
- }
- hdcNew = pdcNew->BaseObject.hHmgr;
-
- pdcNew->dclevel.hdcSave = hdcNew;
- IntGdiCopyToSaveState(pdc, pdcNew);
-
- DC_UnlockDc(pdcNew);
- DC_UnlockDc(pdc);
-
- return hdcNew;
-}
-
-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);
+
+ return TRUE;
}
@@ -252,132 +94,157 @@
return 0;
}
-BOOL APIENTRY
+
+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)
+ HDC hdc,
+ INT iSaveLevel)
+{
+ PDC pdc, pdcSave;
+ HDC hdcSave;
+ PEPROCESS pepCurrentProcess;
+
+ DPRINT("NtGdiRestoreDC(%lx, %d)\n", hdc, iSaveLevel);
+
+ /* Lock the original DC */
+ pdc = DC_LockDc(hdc);
+ if (!pdc)
{
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);
+ ASSERT(pdc->dclevel.lSaveDepth > 0);
+
+ /* Negative values are relative to the stack top */
+ if (iSaveLevel < 0)
+ iSaveLevel = pdc->dclevel.lSaveDepth + iSaveLevel;
+
+ /* Check if we have a valid instance */
+ if (iSaveLevel <= 0 || iSaveLevel >= pdc->dclevel.lSaveDepth)
+ {
+ DPRINT("Illegal save level, requested: %ld, current: %ld\n",
+ iSaveLevel, pdc->dclevel.lSaveDepth);
+ DC_UnlockDc(pdc);
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
- success=TRUE;
- while (dc->dclevel.lSaveDepth >= SaveLevel)
- {
- HDC hdcs = dc->hdcNext;
-
- dcs = DC_LockDc(hdcs);
- if (dcs == NULL)
+ /* Get current process */
+ pepCurrentProcess = PsGetCurrentProcess();
+
+ /* Loop the save levels */
+ while (pdc->dclevel.lSaveDepth > iSaveLevel)
+ {
+ hdcSave = pdc->dclevel.hdcSave;
+
+ /* Set us as the owner */
+ if (!GDIOBJ_SetOwnership(hdcSave, pepCurrentProcess))
{
- DC_UnlockDc(dc);
+ /* Could not get ownership. That's bad! */
+ DPRINT1("Could not get ownership of saved DC (%p) for dc %p!\n",
+ hdcSave, hdc);
return FALSE;
}
- dc->hdcNext = dcs->hdcNext;
- dcs->hdcNext = 0;
-
- if (--dc->dclevel.lSaveDepth < SaveLevel)
+ /* Lock the saved dc */
+ pdcSave = DC_LockDc(hdcSave);
+ if (!pdcSave)
{
- DC_UnlockDc(dc);
- DC_UnlockDc(dcs);
-
- IntGdiSetDCState(hDC, hdcs);
-
- dc = DC_LockDc(hDC);
- if (!dc)
- {
- return FALSE;
- }
+ /* WTF? Internal error! */
+ DPRINT1("Could not lock the saved DC (%p) for dc %p!\n",
+ hdcSave, hdc);
+ DC_UnlockDc(pdc);
+ return FALSE;
+ }
+
+ /* Remove the saved dc from the queue */
+ pdc->dclevel.hdcSave = pdcSave->dclevel.hdcSave;
+
+ /* Decrement save level */
+ pdc->dclevel.lSaveDepth--;
+
+ /* Is this the state we want? */
+ if (pdc->dclevel.lSaveDepth == iSaveLevel)
+ {
+ /* Copy the state back */
+ DC_vCopyState(pdcSave, pdc);
+
// 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)
+ if (pdc->dclevel.hPath && pdc->dclevel.flPath &
DCPATH_SAVE)
{
- PATH_Delete(dc->dclevel.hPath);
- dc->dclevel.hPath = 0;
- dc->dclevel.flPath &= ~DCPATH_SAVE;
+ PATH_Delete(pdc->dclevel.hPath);
+ pdc->dclevel.hPath = 0;
+ pdc->dclevel.flPath &= ~DCPATH_SAVE;
}
}
- else
- {
- DC_UnlockDc(dcs);
- }
- NtGdiDeleteObjectApp(hdcs);
- }
- DC_UnlockDc(dc);
- return success;
-}
-
-
-INT APIENTRY
+
+ /* Delete the saved dc */
+ DC_FreeDC(hdcSave);
+ }
+
+ DC_UnlockDc(pdc);
+
+ DPRINT("Leaving NtGdiRestoreDC\n");
+ return TRUE;
+}
+
+
+INT
+APIENTRY
NtGdiSaveDC(
HDC hDC)
{
- HDC hdcs;
- PDC dc, dcs;
- INT ret;
+ HDC hdcSave;
+ PDC pdc, pdcSave;
+ INT lSaveDepth;
DPRINT("NtGdiSaveDC(%lx)\n", hDC);
- if (!(hdcs = IntGdiGetDCState(hDC)))
- {
- return 0;
- }
-
- dcs = DC_LockDc(hdcs);
- if (dcs == NULL)
- {
+ /* Lock the original dc */
+ pdc = DC_LockDc(hDC);
+ if (pdc == NULL)
+ {
+ DPRINT("Could not lock DC\n");
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
- dc = DC_LockDc(hDC);
- if (dc == NULL)
- {
- DC_UnlockDc(dcs);
- SetLastWin32Error(ERROR_INVALID_HANDLE);
+
+ /* Allocate a new dc */
+ pdcSave = DC_AllocDC(NULL);
+ if (pdcSave == NULL)
+ {
+ DPRINT("Could not allocate a new DC\n");
+ DC_UnlockDc(pdc);
return 0;
}
-
- /*
- * Copy path.
- */
- dcs->dclevel.hPath = dc->dclevel.hPath;
- if (dcs->dclevel.hPath) dcs->dclevel.flPath |= DCPATH_SAVE;
-
- dcs->hdcNext = dc->hdcNext;
- dc->hdcNext = 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;
-}
-
+ hdcSave = pdcSave->BaseObject.hHmgr;
+
+ /* Make it a kernel handle
+ (FIXME: windows handles this different, see wiki)*/
+ GDIOBJ_SetOwnership(hdcSave, NULL);
+
+ /* Copy the current state */
+ DC_vCopyState(pdc, pdcSave);
+
+ /* Copy path. FIXME: why this way? */
+ pdcSave->dclevel.hPath = pdc->dclevel.hPath;
+ pdcSave->dclevel.flPath = pdc->dclevel.flPath | DCPATH_SAVESTATE;
+ if (pdcSave->dclevel.hPath) pdcSave->dclevel.flPath |= DCPATH_SAVE;
+
+ /* Set new dc as save dc */
+ pdc->dclevel.hdcSave = hdcSave;
+
+ /* Increase save depth, return old value */
+ lSaveDepth = pdc->dclevel.lSaveDepth++;
+
+ /* Cleanup and return */
+ DC_UnlockDc(pdcSave);
+ DC_UnlockDc(pdc);
+
+ DPRINT("Leave NtGdiSaveDC: %ld\n", lSaveDepth);
+ return lSaveDepth;
+}
+