[WIN32K]
[reactos.git] / subsystems / win32 / win32k / objects / dcobjs.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Functions for creation and destruction of DCs
5 * FILE: subsystem/win32/win32k/objects/dcobjs.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
7 */
8
9 #include <w32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 VOID
15 FASTCALL
16 DC_vUpdateFillBrush(PDC pdc)
17 {
18 PDC_ATTR pdcattr = pdc->pdcattr;
19 PBRUSH pbrFill;
20
21 /* Check if the brush handle has changed */
22 if (pdcattr->hbrush != pdc->dclevel.pbrFill->BaseObject.hHmgr)
23 {
24 /* Try to lock the new brush */
25 pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush);
26 if (pbrFill)
27 {
28 /* Unlock old brush, set new brush */
29 BRUSH_ShareUnlockBrush(pdc->dclevel.pbrFill);
30 pdc->dclevel.pbrFill = pbrFill;
31
32 /* Mark eboFill as dirty */
33 pdcattr->ulDirty_ |= DIRTY_FILL;
34 }
35 else
36 {
37 /* Invalid brush handle, restore old one */
38 pdcattr->hbrush = pdc->dclevel.pbrFill->BaseObject.hHmgr;
39 }
40 }
41
42 /* Check if the EBRUSHOBJ needs update */
43 if (pdcattr->ulDirty_ & DIRTY_FILL)
44 {
45 /* Update eboFill */
46 EBRUSHOBJ_vUpdate(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
47 }
48
49 /* Check for DC brush */
50 if (pdcattr->hbrush == StockObjects[DC_BRUSH])
51 {
52 /* ROS HACK, should use surf xlate */
53 /* Update the eboFill's solid color */
54 EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboFill, pdcattr->crPenClr);
55 }
56
57 /* Clear flags */
58 pdcattr->ulDirty_ &= ~(DIRTY_FILL | DC_BRUSH_DIRTY);
59 }
60
61 VOID
62 FASTCALL
63 DC_vUpdateLineBrush(PDC pdc)
64 {
65 PDC_ATTR pdcattr = pdc->pdcattr;
66 PBRUSH pbrLine;
67
68 /* Check if the pen handle has changed */
69 if (pdcattr->hpen != pdc->dclevel.pbrLine->BaseObject.hHmgr)
70 {
71 /* Try to lock the new pen */
72 pbrLine = PEN_ShareLockPen(pdcattr->hpen);
73 if (pbrLine)
74 {
75 /* Unlock old brush, set new brush */
76 BRUSH_ShareUnlockBrush(pdc->dclevel.pbrLine);
77 pdc->dclevel.pbrLine = pbrLine;
78
79 /* Mark eboLine as dirty */
80 pdcattr->ulDirty_ |= DIRTY_LINE;
81 }
82 else
83 {
84 /* Invalid pen handle, restore old one */
85 pdcattr->hpen = pdc->dclevel.pbrLine->BaseObject.hHmgr;
86 }
87 }
88
89 /* Check if the EBRUSHOBJ needs update */
90 if (pdcattr->ulDirty_ & DIRTY_LINE)
91 {
92 /* Update eboLine */
93 EBRUSHOBJ_vUpdate(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
94 }
95
96 /* Check for DC pen */
97 if (pdcattr->hpen == StockObjects[DC_PEN])
98 {
99 /* Update the eboLine's solid color */
100 EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboLine, pdcattr->crPenClr);
101 }
102
103 /* Clear flags */
104 pdcattr->ulDirty_ &= ~(DIRTY_LINE | DC_PEN_DIRTY);
105 }
106
107 VOID
108 FASTCALL
109 DC_vUpdateTextBrush(PDC pdc)
110 {
111 PDC_ATTR pdcattr = pdc->pdcattr;
112
113 /* Update the eboText's solid color */
114 EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboText, pdcattr->crForegroundClr);
115
116 /* Clear flag */
117 pdcattr->ulDirty_ &= ~DIRTY_TEXT;
118 }
119
120 VOID
121 FASTCALL
122 DC_vUpdateBackgroundBrush(PDC pdc)
123 {
124 PDC_ATTR pdcattr = pdc->pdcattr;
125
126 if(pdcattr->ulDirty_ & DIRTY_BACKGROUND)
127 EBRUSHOBJ_vUpdate(&pdc->eboBackground, pbrDefaultBrush, pdc);
128
129 /* Update the eboBackground's solid color */
130 EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboBackground, pdcattr->crBackgroundClr);
131
132 /* Clear flag */
133 pdcattr->ulDirty_ &= ~DIRTY_BACKGROUND;
134 }
135
136 HPALETTE
137 FASTCALL
138 GdiSelectPalette(
139 HDC hDC,
140 HPALETTE hpal,
141 BOOL ForceBackground)
142 {
143 PDC pdc;
144 HPALETTE oldPal = NULL;
145 PPALETTE ppal;
146
147 // FIXME: mark the palette as a [fore\back]ground pal
148 pdc = DC_LockDc(hDC);
149 if (!pdc)
150 {
151 return NULL;
152 }
153
154 /* Check if this is a valid palette handle */
155 ppal = PALETTE_ShareLockPalette(hpal);
156 if (!ppal)
157 {
158 DC_UnlockDc(pdc);
159 return NULL;
160 }
161
162 /* Is this a valid palette for this depth? */
163 if ((BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) <= 8
164 && ppal->Mode == PAL_INDEXED) ||
165 (BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) > 8))
166 {
167 /* Get old palette, set new one */
168 oldPal = pdc->dclevel.hpal;
169 pdc->dclevel.hpal = hpal;
170 DC_vSelectPalette(pdc, ppal);
171
172 /* Mark the brushes invalid */
173 pdc->pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE |
174 DIRTY_BACKGROUND | DIRTY_TEXT;
175 }
176
177 PALETTE_ShareUnlockPalette(ppal);
178 DC_UnlockDc(pdc);
179
180 return oldPal;
181 }
182
183 /*
184 * @implemented
185 */
186 HBRUSH
187 APIENTRY
188 NtGdiSelectBrush(
189 IN HDC hDC,
190 IN HBRUSH hBrush)
191 {
192 PDC pDC;
193 HBRUSH hOrgBrush;
194
195 if (hDC == NULL || hBrush == NULL) return NULL;
196
197 pDC = DC_LockDc(hDC);
198 if (!pDC)
199 {
200 return NULL;
201 }
202
203 /* Simply return the user mode value, without checking */
204 hOrgBrush = pDC->pdcattr->hbrush;
205 pDC->pdcattr->hbrush = hBrush;
206 DC_vUpdateFillBrush(pDC);
207
208 DC_UnlockDc(pDC);
209
210 return hOrgBrush;
211 }
212
213 /*
214 * @implemented
215 */
216 HPEN
217 APIENTRY
218 NtGdiSelectPen(
219 IN HDC hDC,
220 IN HPEN hPen)
221 {
222 PDC pDC;
223 HPEN hOrgPen;
224
225 if (hDC == NULL || hPen == NULL) return NULL;
226
227 pDC = DC_LockDc(hDC);
228 if (!pDC)
229 {
230 return NULL;
231 }
232
233 /* Simply return the user mode value, without checking */
234 hOrgPen = pDC->pdcattr->hpen;
235 pDC->pdcattr->hpen = hPen;
236 DC_vUpdateLineBrush(pDC);
237
238 DC_UnlockDc(pDC);
239
240 return hOrgPen;
241 }
242
243 /*
244 * @implemented
245 */
246 HBITMAP
247 APIENTRY
248 NtGdiSelectBitmap(
249 IN HDC hDC,
250 IN HBITMAP hBmp)
251 {
252 PDC pDC;
253 PDC_ATTR pdcattr;
254 HBITMAP hOrgBmp;
255 PSURFACE psurfBmp, psurfOld;
256 HRGN hVisRgn;
257
258 if (hDC == NULL || hBmp == NULL) return NULL;
259
260 pDC = DC_LockDc(hDC);
261 if (!pDC)
262 {
263 return NULL;
264 }
265 pdcattr = pDC->pdcattr;
266
267 /* must be memory dc to select bitmap */
268 if (pDC->dctype != DC_TYPE_MEMORY)
269 {
270 DC_UnlockDc(pDC);
271 return NULL;
272 }
273
274 psurfBmp = SURFACE_LockSurface(hBmp);
275 if (!psurfBmp)
276 {
277 DC_UnlockDc(pDC);
278 return NULL;
279 }
280
281 /* Get the handle for the old bitmap */
282 psurfOld = pDC->dclevel.pSurface;
283 hOrgBmp = psurfOld ? psurfOld->BaseObject.hHmgr : NULL;
284
285 /* Release the old bitmap, reference the new */
286 DC_vSelectSurface(pDC, psurfBmp);
287
288 // If Info DC this is zero and pSurface is moved to DC->pSurfInfo.
289 psurfBmp->hDC = hDC;
290
291 /* FIXME; improve by using a region without a handle and selecting it */
292 hVisRgn = IntSysCreateRectRgn( 0,
293 0,
294 psurfBmp->SurfObj.sizlBitmap.cx,
295 psurfBmp->SurfObj.sizlBitmap.cy);
296
297 /* Release the exclusive lock */
298 SURFACE_UnlockSurface(psurfBmp);
299
300 /* Mark the brushes invalid */
301 pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE;
302
303 DC_UnlockDc(pDC);
304
305 if (hVisRgn)
306 {
307 GdiSelectVisRgn(hDC, hVisRgn);
308 REGION_FreeRgnByHandle(hVisRgn);
309 }
310
311 return hOrgBmp;
312 }
313
314
315 BOOL
316 APIENTRY
317 NtGdiSelectClipPath(
318 HDC hDC,
319 int Mode)
320 {
321 HRGN hrgnPath;
322 PPATH pPath;
323 BOOL success = FALSE;
324 PDC_ATTR pdcattr;
325 PDC pdc;
326
327 pdc = DC_LockDc(hDC);
328 if (!pdc)
329 {
330 SetLastWin32Error(ERROR_INVALID_PARAMETER);
331 return FALSE;
332 }
333 pdcattr = pdc->pdcattr;
334
335 pPath = PATH_LockPath(pdc->dclevel.hPath);
336 if (!pPath)
337 {
338 DC_UnlockDc(pdc);
339 return FALSE;
340 }
341
342 /* Check that path is closed */
343 if (pPath->state != PATH_Closed)
344 {
345 SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
346 DC_UnlockDc(pdc);
347 return FALSE;
348 }
349
350 /* Construct a region from the path */
351 else if (PATH_PathToRegion(pPath, pdcattr->jFillMode, &hrgnPath))
352 {
353 success = GdiExtSelectClipRgn(pdc, hrgnPath, Mode) != ERROR;
354 GreDeleteObject( hrgnPath );
355
356 /* Empty the path */
357 if (success)
358 PATH_EmptyPath(pPath);
359
360 /* FIXME: Should this function delete the path even if it failed? */
361 }
362
363 PATH_UnlockPath(pPath);
364 DC_UnlockDc(pdc);
365
366 return success;
367 }
368
369 HANDLE
370 APIENTRY
371 NtGdiGetDCObject(HDC hDC, INT ObjectType)
372 {
373 HGDIOBJ SelObject;
374 DC *pdc;
375 PDC_ATTR pdcattr;
376
377 /* From Wine: GetCurrentObject does not SetLastError() on a null object */
378 if(!hDC) return NULL;
379
380 if(!(pdc = DC_LockDc(hDC)))
381 {
382 SetLastWin32Error(ERROR_INVALID_HANDLE);
383 return NULL;
384 }
385 pdcattr = pdc->pdcattr;
386
387 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
388 DC_vUpdateFillBrush(pdc);
389
390 if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
391 DC_vUpdateLineBrush(pdc);
392
393 switch(ObjectType)
394 {
395 case GDI_OBJECT_TYPE_EXTPEN:
396 case GDI_OBJECT_TYPE_PEN:
397 SelObject = pdcattr->hpen;
398 break;
399
400 case GDI_OBJECT_TYPE_BRUSH:
401 SelObject = pdcattr->hbrush;
402 break;
403
404 case GDI_OBJECT_TYPE_PALETTE:
405 SelObject = pdc->dclevel.hpal;
406 break;
407
408 case GDI_OBJECT_TYPE_FONT:
409 SelObject = pdcattr->hlfntNew;
410 break;
411
412 case GDI_OBJECT_TYPE_BITMAP:
413 {
414 SURFACE *psurf = pdc->dclevel.pSurface;
415 SelObject = psurf ? psurf->BaseObject.hHmgr : NULL;
416 break;
417 }
418
419 case GDI_OBJECT_TYPE_COLORSPACE:
420 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
421 // SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ?
422 SelObject = NULL;
423 break;
424
425 default:
426 SelObject = NULL;
427 SetLastWin32Error(ERROR_INVALID_PARAMETER);
428 break;
429 }
430
431 DC_UnlockDc(pdc);
432 return SelObject;
433 }
434
435 ULONG
436 APIENTRY
437 NtGdiEnumObjects(
438 IN HDC hdc,
439 IN INT iObjectType,
440 IN ULONG cjBuf,
441 OUT OPTIONAL PVOID pvBuf)
442 {
443 UNIMPLEMENTED;
444 return 0;
445 }
446