Create a branch for working on csrss and co.
[reactos.git] / win32ss / gdi / ntgdi / dcstate.c
1 /*
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: subsystems/win32/win32k/objects/dcstate.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 VOID
15 FASTCALL
16 DC_vCopyState(PDC pdcSrc, PDC pdcDst, BOOL To)
17 {
18 DPRINT("DC_vCopyState(%p, %p)\n", pdcSrc->BaseObject.hHmgr, pdcDst->BaseObject.hHmgr);
19
20 /* Copy full DC attribute */
21 *pdcDst->pdcattr = *pdcSrc->pdcattr;
22
23 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
24 /* The VisRectRegion field needs to be set to a valid state */
25
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....
28
29 /* Copy DC level */
30 pdcDst->dclevel.pColorSpace = pdcSrc->dclevel.pColorSpace;
31 pdcDst->dclevel.lSaveDepth = pdcSrc->dclevel.lSaveDepth;
32 pdcDst->dclevel.hdcSave = pdcSrc->dclevel.hdcSave;
33 pdcDst->dclevel.laPath = pdcSrc->dclevel.laPath;
34 pdcDst->dclevel.ca = pdcSrc->dclevel.ca;
35 pdcDst->dclevel.mxWorldToDevice = pdcSrc->dclevel.mxWorldToDevice;
36 pdcDst->dclevel.mxDeviceToWorld = pdcSrc->dclevel.mxDeviceToWorld;
37 pdcDst->dclevel.mxWorldToPage = pdcSrc->dclevel.mxWorldToPage;
38 pdcDst->dclevel.efM11PtoD = pdcSrc->dclevel.efM11PtoD;
39 pdcDst->dclevel.efM22PtoD = pdcSrc->dclevel.efM22PtoD;
40 pdcDst->dclevel.sizl = pdcSrc->dclevel.sizl;
41 pdcDst->dclevel.hpal = pdcSrc->dclevel.hpal;
42
43 /* Handle references here correctly */
44 DC_vSelectFillBrush(pdcDst, pdcSrc->dclevel.pbrFill);
45 DC_vSelectLineBrush(pdcDst, pdcSrc->dclevel.pbrLine);
46 DC_vSelectPalette(pdcDst, pdcSrc->dclevel.ppal);
47
48 // FIXME: Handle refs
49 pdcDst->dclevel.plfnt = pdcSrc->dclevel.plfnt;
50
51 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
52 if (To) // Copy "To" SaveDC state.
53 {
54 if (pdcSrc->rosdc.hClipRgn)
55 {
56 pdcDst->rosdc.hClipRgn = IntSysCreateRectRgn(0, 0, 0, 0);
57 NtGdiCombineRgn(pdcDst->rosdc.hClipRgn, pdcSrc->rosdc.hClipRgn, 0, RGN_COPY);
58 }
59 // FIXME: Handle prgnMeta!
60 }
61 else // Copy "!To" RestoreDC state.
62 { /* The VisRectRegion field needs to be set to a valid state */
63 GdiExtSelectClipRgn(pdcDst, pdcSrc->rosdc.hClipRgn, RGN_COPY);
64 }
65 }
66
67
68 BOOL FASTCALL
69 IntGdiCleanDC(HDC hDC)
70 {
71 PDC dc;
72 if (!hDC) return FALSE;
73 dc = DC_LockDc(hDC);
74 if (!dc) return FALSE;
75 // Clean the DC
76 if (defaultDCstate)
77 {
78 DC_vCopyState(defaultDCstate, dc, FALSE);
79 /* Update the brushes now, because they reference some objects (the DC palette)
80 * Which belong to the current process, and this DC might be used for another process
81 * after being cleaned up (for GetDC(0) for instance) */
82 DC_vUpdateFillBrush(dc);
83 DC_vUpdateBackgroundBrush(dc);
84 DC_vUpdateLineBrush(dc);
85 DC_vUpdateTextBrush(dc);
86 }
87
88 DC_UnlockDc(dc);
89
90 return TRUE;
91 }
92
93
94 BOOL
95 APIENTRY
96 NtGdiResetDC(
97 IN HDC hdc,
98 IN LPDEVMODEW pdm,
99 OUT PBOOL pbBanding,
100 IN OPTIONAL VOID *pDriverInfo2,
101 OUT VOID *ppUMdhpdev)
102 {
103 UNIMPLEMENTED;
104 return 0;
105 }
106
107
108 VOID
109 NTAPI
110 DC_vRestoreDC(
111 IN PDC pdc,
112 INT iSaveLevel)
113 {
114 HDC hdcSave;
115 PDC pdcSave;
116
117 ASSERT(iSaveLevel > 0);
118 DPRINT("DC_vRestoreDC(%p, %ld)\n", pdc->BaseObject.hHmgr, iSaveLevel);
119
120 /* Loop the save levels */
121 while (pdc->dclevel.lSaveDepth > iSaveLevel)
122 {
123 hdcSave = pdc->dclevel.hdcSave;
124 DPRINT("RestoreDC = %p\n", hdcSave);
125
126 /* Set us as the owner */
127 if (!GreSetObjectOwner(hdcSave, GDI_OBJ_HMGR_POWNED))
128 {
129 /* Could not get ownership. That's bad! */
130 DPRINT1("Could not get ownership of saved DC (%p) for hdc %p!\n",
131 hdcSave, pdc->BaseObject.hHmgr);
132 return;// FALSE;
133 }
134
135 /* Lock the saved dc */
136 pdcSave = DC_LockDc(hdcSave);
137 if (!pdcSave)
138 {
139 /* WTF? Internal error! */
140 DPRINT1("Could not lock the saved DC (%p) for dc %p!\n",
141 hdcSave, pdc->BaseObject.hHmgr);
142 return;// FALSE;
143 }
144
145 /* Remove the saved dc from the queue */
146 pdc->dclevel.hdcSave = pdcSave->dclevel.hdcSave;
147
148 /* Decrement save level */
149 pdc->dclevel.lSaveDepth--;
150
151 /* Is this the state we want? */
152 if (pdc->dclevel.lSaveDepth == iSaveLevel)
153 {
154 /* Copy the state back */
155 DC_vCopyState(pdcSave, pdc, FALSE);
156
157 /* Only memory DC's change their surface */
158 if (pdc->dctype == DCTYPE_MEMORY)
159 DC_vSelectSurface(pdc, pdcSave->dclevel.pSurface);
160
161 // Restore Path by removing it, if the Save flag is set.
162 // BeginPath will takecare of the rest.
163 if (pdc->dclevel.hPath && pdc->dclevel.flPath & DCPATH_SAVE)
164 {
165 PATH_Delete(pdc->dclevel.hPath);
166 pdc->dclevel.hPath = 0;
167 pdc->dclevel.flPath &= ~DCPATH_SAVE;
168 }
169 }
170
171 /* Prevent save dc from being restored */
172 pdcSave->dclevel.lSaveDepth = 1;
173
174 /* Unlock it */
175 DC_UnlockDc(pdcSave);
176 /* Delete the saved dc */
177 GreDeleteObject(hdcSave);
178 }
179
180 DPRINT("Leave DC_vRestoreDC()\n");
181 }
182
183
184
185 BOOL
186 APIENTRY
187 NtGdiRestoreDC(
188 HDC hdc,
189 INT iSaveLevel)
190 {
191 PDC pdc;
192
193 DPRINT("NtGdiRestoreDC(%p, %d)\n", hdc, iSaveLevel);
194
195 /* Lock the original DC */
196 pdc = DC_LockDc(hdc);
197 if (!pdc)
198 {
199 EngSetLastError(ERROR_INVALID_HANDLE);
200 return FALSE;
201 }
202
203 ASSERT(pdc->dclevel.lSaveDepth > 0);
204
205 /* Negative values are relative to the stack top */
206 if (iSaveLevel < 0)
207 iSaveLevel = pdc->dclevel.lSaveDepth + iSaveLevel;
208
209 /* Check if we have a valid instance */
210 if (iSaveLevel <= 0 || iSaveLevel >= pdc->dclevel.lSaveDepth)
211 {
212 DPRINT("Illegal save level, requested: %ld, current: %ld\n",
213 iSaveLevel, pdc->dclevel.lSaveDepth);
214 DC_UnlockDc(pdc);
215 EngSetLastError(ERROR_INVALID_PARAMETER);
216 return FALSE;
217 }
218
219 /* Call the internal function */
220 DC_vRestoreDC(pdc, iSaveLevel);
221
222 DC_UnlockDc(pdc);
223
224 DPRINT("Leave NtGdiRestoreDC\n");
225 return TRUE;
226 }
227
228
229 INT
230 APIENTRY
231 NtGdiSaveDC(
232 HDC hDC)
233 {
234 HDC hdcSave;
235 PDC pdc, pdcSave;
236 INT lSaveDepth;
237
238 DPRINT("NtGdiSaveDC(%p)\n", hDC);
239
240 /* Lock the original dc */
241 pdc = DC_LockDc(hDC);
242 if (pdc == NULL)
243 {
244 DPRINT("Could not lock DC\n");
245 EngSetLastError(ERROR_INVALID_HANDLE);
246 return 0;
247 }
248
249 /* Allocate a new dc */
250 pdcSave = DC_AllocDcWithHandle();
251 if (pdcSave == NULL)
252 {
253 DPRINT("Could not allocate a new DC\n");
254 DC_UnlockDc(pdc);
255 return 0;
256 }
257 hdcSave = pdcSave->BaseObject.hHmgr;
258
259 InterlockedIncrement(&pdc->ppdev->cPdevRefs);
260 DC_vInitDc(pdcSave, DCTYPE_MEMORY, pdc->ppdev);
261
262 /* Handle references here correctly */
263 //pdcSrc->dclevel.pSurface = NULL;
264 //pdcSrc->dclevel.pbrFill = NULL;
265 //pdcSrc->dclevel.pbrLine = NULL;
266 //pdcSrc->dclevel.ppal = NULL;
267
268 /* Make it a kernel handle
269 (FIXME: Windows handles this differently, see Wiki) */
270 GDIOBJ_vSetObjectOwner(&pdcSave->BaseObject, GDI_OBJ_HMGR_PUBLIC);
271
272 /* Copy the current state */
273 DC_vCopyState(pdc, pdcSave, TRUE);
274
275 /* Only memory DC's change their surface */
276 if (pdc->dctype == DCTYPE_MEMORY)
277 DC_vSelectSurface(pdcSave, pdc->dclevel.pSurface);
278
279 /* Copy path */
280 /* FIXME: Why this way? */
281 pdcSave->dclevel.hPath = pdc->dclevel.hPath;
282 pdcSave->dclevel.flPath = pdc->dclevel.flPath | DCPATH_SAVESTATE;
283 if (pdcSave->dclevel.hPath) pdcSave->dclevel.flPath |= DCPATH_SAVE;
284
285 /* Set new dc as save dc */
286 pdc->dclevel.hdcSave = hdcSave;
287
288 /* Increase save depth, return old value */
289 lSaveDepth = pdc->dclevel.lSaveDepth++;
290
291 /* Cleanup and return */
292 DC_UnlockDc(pdcSave);
293 DC_UnlockDc(pdc);
294
295 DPRINT("Leave NtGdiSaveDC: %ld, hdcSave = %p\n", lSaveDepth, hdcSave);
296 return lSaveDepth;
297 }
298
299 /* EOF */