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