2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Functions for saving and restoring dc states
5 * FILE: win32ss/gdi/ntgdi/dcstate.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
16 DC_vCopyState(PDC pdcSrc
, PDC pdcDst
, BOOL To
)
18 DPRINT("DC_vCopyState(%p, %p)\n", pdcSrc
->BaseObject
.hHmgr
, pdcDst
->BaseObject
.hHmgr
);
20 /* Copy full DC attribute */
21 *pdcDst
->pdcattr
= *pdcSrc
->pdcattr
;
23 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
24 /* The VisRectRegion field needs to be set to a valid state */
26 /* Mark some fields as dirty */
27 pdcDst
->pdcattr
->ulDirty_
|= (DIRTY_FILL
|DIRTY_LINE
|DIRTY_TEXT
|DIRTY_BACKGROUND
|DIRTY_CHARSET
|DC_ICM_NOT_CALIBRATED
|DC_ICM_NOT_SET
); // Note: Use if, To is FALSE....
30 pdcDst
->dclevel
.pColorSpace
= pdcSrc
->dclevel
.pColorSpace
;
31 pdcDst
->dclevel
.laPath
= pdcSrc
->dclevel
.laPath
;
32 pdcDst
->dclevel
.ca
= pdcSrc
->dclevel
.ca
;
33 pdcDst
->dclevel
.mxWorldToDevice
= pdcSrc
->dclevel
.mxWorldToDevice
;
34 pdcDst
->dclevel
.mxDeviceToWorld
= pdcSrc
->dclevel
.mxDeviceToWorld
;
35 pdcDst
->dclevel
.mxWorldToPage
= pdcSrc
->dclevel
.mxWorldToPage
;
36 pdcDst
->dclevel
.efM11PtoD
= pdcSrc
->dclevel
.efM11PtoD
;
37 pdcDst
->dclevel
.efM22PtoD
= pdcSrc
->dclevel
.efM22PtoD
;
38 pdcDst
->dclevel
.sizl
= pdcSrc
->dclevel
.sizl
;
39 pdcDst
->dclevel
.hpal
= pdcSrc
->dclevel
.hpal
;
41 /* Handle references here correctly */
42 DC_vSelectFillBrush(pdcDst
, pdcSrc
->dclevel
.pbrFill
);
43 DC_vSelectLineBrush(pdcDst
, pdcSrc
->dclevel
.pbrLine
);
44 DC_vSelectPalette(pdcDst
, pdcSrc
->dclevel
.ppal
);
46 /* Dereference the old font, reference the new one */
47 if (pdcDst
->dclevel
.plfnt
) LFONT_ShareUnlockFont(pdcDst
->dclevel
.plfnt
); /// @todo should aways be != NULL
48 GDIOBJ_vReferenceObjectByPointer(&pdcSrc
->dclevel
.plfnt
->BaseObject
);
49 pdcDst
->dclevel
.plfnt
= pdcSrc
->dclevel
.plfnt
;
51 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
54 IntGdiExtSelectClipRgn(pdcDst
, pdcSrc
->dclevel
.prgnClip
, RGN_COPY
);
55 if (pdcDst
->dclevel
.prgnMeta
)
57 REGION_Delete(pdcDst
->dclevel
.prgnMeta
);
58 pdcDst
->dclevel
.prgnMeta
= NULL
;
60 if (pdcSrc
->dclevel
.prgnMeta
)
62 pdcDst
->dclevel
.prgnMeta
= IntSysCreateRectpRgn(0, 0, 0, 0);
63 IntGdiCombineRgn(pdcDst
->dclevel
.prgnMeta
, pdcSrc
->dclevel
.prgnMeta
, NULL
, RGN_COPY
);
65 pdcDst
->fs
|= DC_FLAG_DIRTY_RAO
;
72 IntGdiCleanDC(HDC hDC
)
75 if (!hDC
) return FALSE
;
77 if (!dc
) return FALSE
;
81 DC_vCopyState(defaultDCstate
, dc
, FALSE
);
82 /* Update the brushes now, because they reference some objects (the DC palette)
83 * Which belong to the current process, and this DC might be used for another process
84 * after being cleaned up (for GetDC(0) for instance) */
85 DC_vUpdateFillBrush(dc
);
86 DC_vUpdateBackgroundBrush(dc
);
87 DC_vUpdateLineBrush(dc
);
88 DC_vUpdateTextBrush(dc
);
91 // Remove Path and reset flags.
92 if (dc
->dclevel
.hPath
)
94 DPRINT("Clean DC Remove Path\n");
95 if (!PATH_Delete(dc
->dclevel
.hPath
))
97 DPRINT1("Failed to remove Path\n");
99 dc
->dclevel
.hPath
= 0;
100 dc
->dclevel
.flPath
= 0;
103 /* DC_vCopyState frees the Clip rgn and the Meta rgn. Take care of the other ones
104 * There is no need to clear prgnVis, as UserGetDC updates it immediately. */
106 REGION_Delete(dc
->prgnRao
);
108 REGION_Delete(dc
->prgnAPI
);
109 dc
->prgnRao
= dc
->prgnAPI
= NULL
;
111 dc
->fs
|= DC_FLAG_DIRTY_RAO
;
124 _Out_ PBOOL pbBanding
,
125 _In_opt_ DRIVER_INFO_2W
*pDriverInfo2
,
126 _At_((PUMDHPDEV
*)ppUMdhpdev
, _Out_
) PVOID ppUMdhpdev
)
128 /* According to a comment in Windows SDK the size of the buffer for
129 pdm is (pdm->dmSize + pdm->dmDriverExtra) */
144 NT_ASSERT(iSaveLevel
> 0);
145 DPRINT("DC_vRestoreDC(%p, %ld)\n", pdc
->BaseObject
.hHmgr
, iSaveLevel
);
147 /* Loop the save levels */
148 while (pdc
->dclevel
.lSaveDepth
> iSaveLevel
)
150 hdcSave
= pdc
->dclevel
.hdcSave
;
151 DPRINT("RestoreDC = %p\n", hdcSave
);
153 /* Set us as the owner */
154 if (!GreSetObjectOwner(hdcSave
, GDI_OBJ_HMGR_POWNED
))
156 /* Could not get ownership. That's bad! */
157 DPRINT1("Could not get ownership of saved DC (%p) for hdc %p!\n",
158 hdcSave
, pdc
->BaseObject
.hHmgr
);
163 /* Lock the saved dc */
164 pdcSave
= DC_LockDc(hdcSave
);
167 /* WTF? Internal error! */
168 DPRINT1("Could not lock the saved DC (%p) for dc %p!\n",
169 hdcSave
, pdc
->BaseObject
.hHmgr
);
174 /* Remove the saved dc from the queue */
175 pdc
->dclevel
.hdcSave
= pdcSave
->dclevel
.hdcSave
;
177 /* Decrement save level */
178 pdc
->dclevel
.lSaveDepth
--;
180 /* Is this the state we want? */
181 if (pdc
->dclevel
.lSaveDepth
== iSaveLevel
)
183 /* Copy the state back */
184 DC_vCopyState(pdcSave
, pdc
, FALSE
);
186 /* Only memory DC's change their surface */
187 if (pdc
->dctype
== DCTYPE_MEMORY
)
188 DC_vSelectSurface(pdc
, pdcSave
->dclevel
.pSurface
);
190 if (pdcSave
->dclevel
.hPath
)
192 PATH_RestorePath( pdc
, pdcSave
);
196 /* Prevent save dc from being restored */
197 pdcSave
->dclevel
.lSaveDepth
= 1;
200 DC_UnlockDc(pdcSave
);
201 /* Delete the saved dc */
202 GreDeleteObject(hdcSave
);
205 DPRINT("Leave DC_vRestoreDC()\n");
218 DPRINT("NtGdiRestoreDC(%p, %d)\n", hdc
, iSaveLevel
);
220 /* Lock the original DC */
221 pdc
= DC_LockDc(hdc
);
224 EngSetLastError(ERROR_INVALID_HANDLE
);
228 ASSERT(pdc
->dclevel
.lSaveDepth
> 0);
230 /* Negative values are relative to the stack top */
232 iSaveLevel
= pdc
->dclevel
.lSaveDepth
+ iSaveLevel
;
234 /* Check if we have a valid instance */
235 if (iSaveLevel
<= 0 || iSaveLevel
>= pdc
->dclevel
.lSaveDepth
)
237 DPRINT("Illegal save level, requested: %ld, current: %ld\n",
238 iSaveLevel
, pdc
->dclevel
.lSaveDepth
);
240 EngSetLastError(ERROR_INVALID_PARAMETER
);
244 /* Call the internal function */
245 DC_vRestoreDC(pdc
, iSaveLevel
);
249 DPRINT("Leave NtGdiRestoreDC\n");
263 DPRINT("NtGdiSaveDC(%p)\n", hDC
);
265 /* Lock the original dc */
266 pdc
= DC_LockDc(hDC
);
269 DPRINT("Could not lock DC\n");
270 EngSetLastError(ERROR_INVALID_HANDLE
);
274 /* Allocate a new dc */
275 pdcSave
= DC_AllocDcWithHandle(GDILoObjType_LO_DC_TYPE
);
278 DPRINT("Could not allocate a new DC\n");
282 hdcSave
= pdcSave
->BaseObject
.hHmgr
;
284 InterlockedIncrement(&pdc
->ppdev
->cPdevRefs
);
285 DC_vInitDc(pdcSave
, DCTYPE_MEMORY
, pdc
->ppdev
);
287 /* Handle references here correctly */
288 //pdcSrc->dclevel.pSurface = NULL;
289 //pdcSrc->dclevel.pbrFill = NULL;
290 //pdcSrc->dclevel.pbrLine = NULL;
291 //pdcSrc->dclevel.ppal = NULL;
293 /* Make it a kernel handle
294 (FIXME: Windows handles this differently, see Wiki) */
295 GDIOBJ_vSetObjectOwner(&pdcSave
->BaseObject
, GDI_OBJ_HMGR_PUBLIC
);
297 /* Copy the current state */
298 DC_vCopyState(pdc
, pdcSave
, FALSE
);
300 /* Only memory DC's change their surface */
301 if (pdc
->dctype
== DCTYPE_MEMORY
)
302 DC_vSelectSurface(pdcSave
, pdc
->dclevel
.pSurface
);
305 if (pdc
->dclevel
.hPath
)
307 PATH_SavePath( pdcSave
, pdc
);
309 pdcSave
->dclevel
.flPath
= pdc
->dclevel
.flPath
| DCPATH_SAVESTATE
;
311 /* Set new dc as save dc */
312 pdcSave
->dclevel
.hdcSave
= pdc
->dclevel
.hdcSave
;
313 pdc
->dclevel
.hdcSave
= hdcSave
;
315 /* Increase save depth, return old value */
316 lSaveDepth
= pdc
->dclevel
.lSaveDepth
++;
318 /* Cleanup and return */
319 DC_UnlockDc(pdcSave
);
322 DPRINT("Leave NtGdiSaveDC: %ld, hdcSave = %p\n", lSaveDepth
, hdcSave
);