[ros-diffs] [tkreuzer] 40219: 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.

tkreuzer at svn.reactos.org tkreuzer at svn.reactos.org
Wed Mar 25 05:21:00 CET 2009


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/include/dc.h?rev=40219&r1=40218&r2=40219&view=diff
==============================================================================
--- 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/ntuser/windc.c?rev=40219&r1=40218&r2=40219&view=diff
==============================================================================
--- 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/objects/dclife.c?rev=40219&r1=40218&r2=40219&view=diff
==============================================================================
--- 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/objects/dcstate.c?rev=40219&r1=40218&r2=40219&view=diff
==============================================================================
--- 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;
+}
+



More information about the Ros-diffs mailing list