2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Functions for saving and restoring dc states
5 * FILE: subsystem/win32/win32k/objects/dcstate.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
16 DC_vCopyState(PDC pdcSrc
, PDC pdcDst
, BOOL To
)
18 /* Copy full DC attribute */
19 *pdcDst
->pdcattr
= *pdcSrc
->pdcattr
;
21 /* Mark some fields as dirty */
22 pdcDst
->pdcattr
->ulDirty_
|= 0x0012001f; // Note: Use if, To is FALSE....
25 pdcDst
->dclevel
.pColorSpace
= pdcSrc
->dclevel
.pColorSpace
;
26 pdcDst
->dclevel
.lSaveDepth
= pdcSrc
->dclevel
.lSaveDepth
;
27 pdcDst
->dclevel
.hdcSave
= pdcSrc
->dclevel
.hdcSave
;
28 pdcDst
->dclevel
.laPath
= pdcSrc
->dclevel
.laPath
;
29 pdcDst
->dclevel
.ca
= pdcSrc
->dclevel
.ca
;
30 pdcDst
->dclevel
.mxWorldToDevice
= pdcSrc
->dclevel
.mxWorldToDevice
;
31 pdcDst
->dclevel
.mxDeviceToWorld
= pdcSrc
->dclevel
.mxDeviceToWorld
;
32 pdcDst
->dclevel
.mxWorldToPage
= pdcSrc
->dclevel
.mxWorldToPage
;
33 pdcDst
->dclevel
.efM11PtoD
= pdcSrc
->dclevel
.efM11PtoD
;
34 pdcDst
->dclevel
.efM22PtoD
= pdcSrc
->dclevel
.efM22PtoD
;
35 pdcDst
->dclevel
.sizl
= pdcSrc
->dclevel
.sizl
;
36 pdcDst
->dclevel
.hpal
= pdcSrc
->dclevel
.hpal
;
38 /* Handle references here correctly */
39 DC_vSelectSurface(pdcDst
, pdcSrc
->dclevel
.pSurface
);
40 DC_vSelectFillBrush(pdcDst
, pdcSrc
->dclevel
.pbrFill
);
41 DC_vSelectLineBrush(pdcDst
, pdcSrc
->dclevel
.pbrLine
);
42 DC_vSelectPalette(pdcDst
, pdcSrc
->dclevel
.ppal
);
45 pdcDst
->dclevel
.plfnt
= pdcSrc
->dclevel
.plfnt
;
47 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
48 if (To
) // Copy "To" SaveDC state.
50 if (pdcSrc
->rosdc
.hClipRgn
)
52 pdcDst
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
53 NtGdiCombineRgn(pdcDst
->rosdc
.hClipRgn
, pdcSrc
->rosdc
.hClipRgn
, 0, RGN_COPY
);
55 // FIXME! Handle prgnMeta!
57 else // Copy "!To" RestoreDC state.
58 { /* The VisRectRegion field needs to be set to a valid state */
59 GdiExtSelectClipRgn(pdcDst
, pdcSrc
->rosdc
.hClipRgn
, RGN_COPY
);
65 IntGdiCleanDC(HDC hDC
)
68 if (!hDC
) return FALSE
;
70 if (!dc
) return FALSE
;
72 if (defaultDCstate
) DC_vCopyState(defaultDCstate
, dc
, FALSE
);
86 IN OPTIONAL VOID
*pDriverInfo2
,
103 DPRINT("NtGdiRestoreDC(%lx, %d)\n", hdc
, iSaveLevel
);
105 /* Lock the original DC */
106 pdc
= DC_LockDc(hdc
);
109 SetLastWin32Error(ERROR_INVALID_HANDLE
);
113 ASSERT(pdc
->dclevel
.lSaveDepth
> 0);
115 /* Negative values are relative to the stack top */
117 iSaveLevel
= pdc
->dclevel
.lSaveDepth
+ iSaveLevel
;
119 /* Check if we have a valid instance */
120 if (iSaveLevel
<= 0 || iSaveLevel
>= pdc
->dclevel
.lSaveDepth
)
122 DPRINT("Illegal save level, requested: %ld, current: %ld\n",
123 iSaveLevel
, pdc
->dclevel
.lSaveDepth
);
125 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
129 /* Loop the save levels */
130 while (pdc
->dclevel
.lSaveDepth
> iSaveLevel
)
132 hdcSave
= pdc
->dclevel
.hdcSave
;
134 /* Set us as the owner */
135 if (!IntGdiSetDCOwnerEx(hdcSave
, GDI_OBJ_HMGR_POWNED
, FALSE
))
137 /* Could not get ownership. That's bad! */
138 DPRINT1("Could not get ownership of saved DC (%p) for dc %p!\n",
143 /* Lock the saved dc */
144 pdcSave
= DC_LockDc(hdcSave
);
147 /* WTF? Internal error! */
148 DPRINT1("Could not lock the saved DC (%p) for dc %p!\n",
154 /* Remove the saved dc from the queue */
155 pdc
->dclevel
.hdcSave
= pdcSave
->dclevel
.hdcSave
;
157 /* Decrement save level */
158 pdc
->dclevel
.lSaveDepth
--;
160 /* Is this the state we want? */
161 if (pdc
->dclevel
.lSaveDepth
== iSaveLevel
)
163 /* Copy the state back */
164 DC_vCopyState(pdcSave
, pdc
, FALSE
);
166 // Restore Path by removing it, if the Save flag is set.
167 // BeginPath will takecare of the rest.
168 if (pdc
->dclevel
.hPath
&& pdc
->dclevel
.flPath
& DCPATH_SAVE
)
170 PATH_Delete(pdc
->dclevel
.hPath
);
171 pdc
->dclevel
.hPath
= 0;
172 pdc
->dclevel
.flPath
&= ~DCPATH_SAVE
;
174 // Attempt to plug the leak!
175 if (pdcSave
->rosdc
.hClipRgn
)
177 DPRINT("Have hClipRgn!\n");
178 REGION_FreeRgnByHandle(pdcSave
->rosdc
.hClipRgn
);
180 // FIXME! Handle prgnMeta!
183 /* Delete the saved dc */
184 GreDeleteObject(hdcSave
);
189 DPRINT("Leaving NtGdiRestoreDC\n");
203 DPRINT("NtGdiSaveDC(%lx)\n", hDC
);
205 /* Lock the original dc */
206 pdc
= DC_LockDc(hDC
);
209 DPRINT("Could not lock DC\n");
210 SetLastWin32Error(ERROR_INVALID_HANDLE
);
214 /* Allocate a new dc */
215 pdcSave
= DC_AllocDC(NULL
);
218 DPRINT("Could not allocate a new DC\n");
222 hdcSave
= pdcSave
->BaseObject
.hHmgr
;
224 /* Copy the current state */
225 DC_vCopyState(pdc
, pdcSave
, TRUE
);
227 /* Make it a kernel handle
228 (FIXME: windows handles this different, see wiki)*/
229 IntGdiSetDCOwnerEx(hdcSave
, GDI_OBJ_HMGR_NONE
, FALSE
);
231 /* Copy path. FIXME: why this way? */
232 pdcSave
->dclevel
.hPath
= pdc
->dclevel
.hPath
;
233 pdcSave
->dclevel
.flPath
= pdc
->dclevel
.flPath
| DCPATH_SAVESTATE
;
234 if (pdcSave
->dclevel
.hPath
) pdcSave
->dclevel
.flPath
|= DCPATH_SAVE
;
236 /* Set new dc as save dc */
237 pdc
->dclevel
.hdcSave
= hdcSave
;
239 /* Increase save depth, return old value */
240 lSaveDepth
= pdc
->dclevel
.lSaveDepth
++;
242 /* Cleanup and return */
243 DC_UnlockDc(pdcSave
);
246 DPRINT("Leave NtGdiSaveDC: %ld\n", lSaveDepth
);