Sync with trunk head (r48786)
[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 <win32k.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 /* Timo : The text brush should never be changed.
114 * Jérôme : Yeah, but its palette must be updated anyway! */
115 if(pdcattr->ulDirty_ & DIRTY_TEXT)
116 EBRUSHOBJ_vUpdate(&pdc->eboText, pbrDefaultBrush, pdc);
117
118 /* Update the eboText's solid color */
119 EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboText, pdcattr->crForegroundClr);
120
121 /* Clear flag */
122 pdcattr->ulDirty_ &= ~DIRTY_TEXT;
123 }
124
125 VOID
126 FASTCALL
127 DC_vUpdateBackgroundBrush(PDC pdc)
128 {
129 PDC_ATTR pdcattr = pdc->pdcattr;
130
131 if(pdcattr->ulDirty_ & DIRTY_BACKGROUND)
132 EBRUSHOBJ_vUpdate(&pdc->eboBackground, pbrDefaultBrush, pdc);
133
134 /* Update the eboBackground's solid color */
135 EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboBackground, pdcattr->crBackgroundClr);
136
137 /* Clear flag */
138 pdcattr->ulDirty_ &= ~DIRTY_BACKGROUND;
139 }
140
141 HPALETTE
142 FASTCALL
143 GdiSelectPalette(
144 HDC hDC,
145 HPALETTE hpal,
146 BOOL ForceBackground)
147 {
148 PDC pdc;
149 HPALETTE oldPal = NULL;
150 PPALETTE ppal;
151
152 // FIXME: mark the palette as a [fore\back]ground pal
153 pdc = DC_LockDc(hDC);
154 if (!pdc)
155 {
156 return NULL;
157 }
158
159 /* Check if this is a valid palette handle */
160 ppal = PALETTE_ShareLockPalette(hpal);
161 if (!ppal)
162 {
163 DC_UnlockDc(pdc);
164 return NULL;
165 }
166
167 /* Is this a valid palette for this depth? */
168 if ((BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) <= 8
169 && ppal->Mode == PAL_INDEXED) ||
170 (BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) > 8))
171 {
172 /* Get old palette, set new one */
173 oldPal = pdc->dclevel.hpal;
174 pdc->dclevel.hpal = hpal;
175 DC_vSelectPalette(pdc, ppal);
176
177 /* Mark the brushes invalid */
178 pdc->pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE |
179 DIRTY_BACKGROUND | DIRTY_TEXT;
180 }
181
182 PALETTE_ShareUnlockPalette(ppal);
183 DC_UnlockDc(pdc);
184
185 return oldPal;
186 }
187
188 /*
189 * @implemented
190 */
191 HBRUSH
192 APIENTRY
193 NtGdiSelectBrush(
194 IN HDC hDC,
195 IN HBRUSH hBrush)
196 {
197 PDC pDC;
198 HBRUSH hOrgBrush;
199
200 if (hDC == NULL || hBrush == NULL) return NULL;
201
202 pDC = DC_LockDc(hDC);
203 if (!pDC)
204 {
205 return NULL;
206 }
207
208 /* Simply return the user mode value, without checking */
209 hOrgBrush = pDC->pdcattr->hbrush;
210 pDC->pdcattr->hbrush = hBrush;
211 DC_vUpdateFillBrush(pDC);
212
213 DC_UnlockDc(pDC);
214
215 return hOrgBrush;
216 }
217
218 /*
219 * @implemented
220 */
221 HPEN
222 APIENTRY
223 NtGdiSelectPen(
224 IN HDC hDC,
225 IN HPEN hPen)
226 {
227 PDC pDC;
228 HPEN hOrgPen;
229
230 if (hDC == NULL || hPen == NULL) return NULL;
231
232 pDC = DC_LockDc(hDC);
233 if (!pDC)
234 {
235 return NULL;
236 }
237
238 /* Simply return the user mode value, without checking */
239 hOrgPen = pDC->pdcattr->hpen;
240 pDC->pdcattr->hpen = hPen;
241 DC_vUpdateLineBrush(pDC);
242
243 DC_UnlockDc(pDC);
244
245 return hOrgPen;
246 }
247
248 /*
249 * @implemented
250 */
251 HBITMAP
252 APIENTRY
253 NtGdiSelectBitmap(
254 IN HDC hDC,
255 IN HBITMAP hBmp)
256 {
257 PDC pDC;
258 PDC_ATTR pdcattr;
259 HBITMAP hOrgBmp;
260 PSURFACE psurfBmp, psurfOld;
261 HRGN hVisRgn;
262
263 if (hDC == NULL || hBmp == NULL) return NULL;
264
265 pDC = DC_LockDc(hDC);
266 if (!pDC)
267 {
268 return NULL;
269 }
270 pdcattr = pDC->pdcattr;
271
272 /* must be memory dc to select bitmap */
273 if (pDC->dctype != DC_TYPE_MEMORY)
274 {
275 DC_UnlockDc(pDC);
276 return NULL;
277 }
278
279 psurfBmp = SURFACE_LockSurface(hBmp);
280 if (!psurfBmp)
281 {
282 DC_UnlockDc(pDC);
283 return NULL;
284 }
285
286 /* Get the handle for the old bitmap */
287 ASSERT(pDC->dclevel.pSurface);
288 hOrgBmp = pDC->dclevel.pSurface->BaseObject.hHmgr;
289
290 /* Lock it, to be sure while we mess with it*/
291 psurfOld = SURFACE_LockSurface(hOrgBmp);
292
293 /* Reset hdc, this surface isn't selected anymore */
294 psurfOld->hdc = NULL;
295
296 /* Release the old bitmap, reference the new */
297 DC_vSelectSurface(pDC, psurfBmp);
298
299 /* And unlock it, now we're done */
300 SURFACE_UnlockSurface(psurfOld);
301
302 // If Info DC this is zero and pSurface is moved to DC->pSurfInfo.
303 psurfBmp->hdc = hDC;
304
305
306 /* FIXME; improve by using a region without a handle and selecting it */
307 hVisRgn = IntSysCreateRectRgn( 0,
308 0,
309 psurfBmp->SurfObj.sizlBitmap.cx,
310 psurfBmp->SurfObj.sizlBitmap.cy);
311
312 if(psurfBmp->hSecure)
313 {
314 /* Set DIBSECTION attribute */
315 pdcattr->ulDirty_ |= DC_DIBSECTION;
316 }
317 else
318 {
319 pdcattr->ulDirty_ &= ~DC_DIBSECTION;
320 }
321
322 /* Release the exclusive lock */
323 SURFACE_UnlockSurface(psurfBmp);
324
325 /* Mark the brushes invalid */
326 pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE;
327
328 DC_UnlockDc(pDC);
329
330 if (hVisRgn)
331 {
332 GdiSelectVisRgn(hDC, hVisRgn);
333 REGION_FreeRgnByHandle(hVisRgn);
334 }
335
336 return hOrgBmp;
337 }
338
339
340 BOOL
341 APIENTRY
342 NtGdiSelectClipPath(
343 HDC hDC,
344 int Mode)
345 {
346 HRGN hrgnPath;
347 PPATH pPath;
348 BOOL success = FALSE;
349 PDC_ATTR pdcattr;
350 PDC pdc;
351
352 pdc = DC_LockDc(hDC);
353 if (!pdc)
354 {
355 SetLastWin32Error(ERROR_INVALID_PARAMETER);
356 return FALSE;
357 }
358 pdcattr = pdc->pdcattr;
359
360 pPath = PATH_LockPath(pdc->dclevel.hPath);
361 if (!pPath)
362 {
363 DC_UnlockDc(pdc);
364 return FALSE;
365 }
366
367 /* Check that path is closed */
368 if (pPath->state != PATH_Closed)
369 {
370 SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
371 DC_UnlockDc(pdc);
372 return FALSE;
373 }
374
375 /* Construct a region from the path */
376 else if (PATH_PathToRegion(pPath, pdcattr->jFillMode, &hrgnPath))
377 {
378 success = GdiExtSelectClipRgn(pdc, hrgnPath, Mode) != ERROR;
379 GreDeleteObject( hrgnPath );
380
381 /* Empty the path */
382 if (success)
383 PATH_EmptyPath(pPath);
384
385 /* FIXME: Should this function delete the path even if it failed? */
386 }
387
388 PATH_UnlockPath(pPath);
389 DC_UnlockDc(pdc);
390
391 return success;
392 }
393
394 HANDLE
395 APIENTRY
396 NtGdiGetDCObject(HDC hDC, INT ObjectType)
397 {
398 HGDIOBJ SelObject;
399 DC *pdc;
400 PDC_ATTR pdcattr;
401
402 /* From Wine: GetCurrentObject does not SetLastError() on a null object */
403 if(!hDC) return NULL;
404
405 if(!(pdc = DC_LockDc(hDC)))
406 {
407 SetLastWin32Error(ERROR_INVALID_HANDLE);
408 return NULL;
409 }
410 pdcattr = pdc->pdcattr;
411
412 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
413 DC_vUpdateFillBrush(pdc);
414
415 if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
416 DC_vUpdateLineBrush(pdc);
417
418 switch(ObjectType)
419 {
420 case GDI_OBJECT_TYPE_EXTPEN:
421 case GDI_OBJECT_TYPE_PEN:
422 SelObject = pdcattr->hpen;
423 break;
424
425 case GDI_OBJECT_TYPE_BRUSH:
426 SelObject = pdcattr->hbrush;
427 break;
428
429 case GDI_OBJECT_TYPE_PALETTE:
430 SelObject = pdc->dclevel.hpal;
431 break;
432
433 case GDI_OBJECT_TYPE_FONT:
434 SelObject = pdcattr->hlfntNew;
435 break;
436
437 case GDI_OBJECT_TYPE_BITMAP:
438 {
439 SURFACE *psurf = pdc->dclevel.pSurface;
440 SelObject = psurf ? psurf->BaseObject.hHmgr : NULL;
441 break;
442 }
443
444 case GDI_OBJECT_TYPE_COLORSPACE:
445 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
446 // SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ?
447 SelObject = NULL;
448 break;
449
450 default:
451 SelObject = NULL;
452 SetLastWin32Error(ERROR_INVALID_PARAMETER);
453 break;
454 }
455
456 DC_UnlockDc(pdc);
457 return SelObject;
458 }
459
460 ULONG
461 APIENTRY
462 NtGdiEnumObjects(
463 IN HDC hdc,
464 IN INT iObjectType,
465 IN ULONG cjBuf,
466 OUT OPTIONAL PVOID pvBuf)
467 {
468 UNIMPLEMENTED;
469 return 0;
470 }
471