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