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