Move NtGdiSelectBitmap to dcobjs.c, implement DC_vSelectFillBrush and DC_vSelectLineB...
[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 <w32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14
15 VOID
16 FASTCALL
17 DC_vUpdateFillBrush(PDC pdc)
18 {
19 PDC_ATTR pdcattr = pdc->pdcattr;
20 PBRUSH pbrFill;
21 XLATEOBJ *pxlo;
22 ULONG iSolidColor;
23
24 /* ROS HACK, should use surf xlate */
25 pxlo = pdc->rosdc.XlatePen;
26
27 /* Check if the brush handle has changed */
28 if (pdcattr->hbrush != pdc->dclevel.pbrFill->BaseObject.hHmgr)
29 {
30 /* Try to lock the new brush */
31 pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush);
32 if (pbrFill)
33 {
34 /* Unlock old brush, set new brush */
35 BRUSH_ShareUnlockBrush(pdc->dclevel.pbrFill);
36 pdc->dclevel.pbrFill = pbrFill;
37
38 /* Update eboFill, realizing it, if needed */
39 EBRUSHOBJ_vUpdate(&pdc->eboFill, pbrFill, pxlo);
40 }
41 else
42 {
43 /* Invalid brush handle, restore old one */
44 pdcattr->hbrush = pdc->dclevel.pbrFill->BaseObject.hHmgr;
45 }
46 }
47
48 /* Check for DC brush */
49 if (pdcattr->hbrush == StockObjects[DC_BRUSH])
50 {
51 /* Translate the color to the target format */
52 iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crPenClr);
53
54 /* Update the eboFill's solid color */
55 EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboFill, iSolidColor);
56 }
57
58 /* Clear flags */
59 pdcattr->ulDirty_ &= ~(DIRTY_FILL | DC_BRUSH_DIRTY);
60 }
61
62 VOID
63 FASTCALL
64 DC_vUpdateLineBrush(PDC pdc)
65 {
66 PDC_ATTR pdcattr = pdc->pdcattr;
67 PBRUSH pbrLine;
68 XLATEOBJ *pxlo;
69 ULONG iSolidColor;
70
71 /* ROS HACK, should use surf xlate */
72 pxlo = pdc->rosdc.XlatePen;
73
74 /* Check if the pen handle has changed */
75 if (pdcattr->hpen != pdc->dclevel.pbrLine->BaseObject.hHmgr)
76 {
77 /* Try to lock the new pen */
78 pbrLine = BRUSH_ShareLockBrush(pdcattr->hpen);
79 if (pbrLine)
80 {
81 /* Unlock old brush, set new brush */
82 BRUSH_ShareUnlockBrush(pdc->dclevel.pbrLine);
83 pdc->dclevel.pbrLine = pbrLine;
84
85 /* Update eboLine, realizing it, if needed */
86 EBRUSHOBJ_vUpdate(&pdc->eboLine, pbrLine, pxlo);
87 }
88 else
89 {
90 /* Invalid pen handle, restore old one */
91 pdcattr->hpen = pdc->dclevel.pbrLine->BaseObject.hHmgr;
92 }
93 }
94
95 /* Check for DC pen */
96 if (pdcattr->hpen == StockObjects[DC_PEN])
97 {
98 /* Translate the color to the target format */
99 iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crPenClr);
100
101 /* Update the eboLine's solid color */
102 EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboLine, iSolidColor);
103 }
104
105 /* Clear flag */
106 pdcattr->ulDirty_ &= ~DIRTY_LINE;
107 }
108
109 VOID
110 FASTCALL
111 DC_vUpdateTextBrush(PDC pdc)
112 {
113 PDC_ATTR pdcattr = pdc->pdcattr;
114 XLATEOBJ *pxlo;
115 ULONG iSolidColor;
116
117 /* ROS HACK, should use surf xlate */
118 pxlo = pdc->rosdc.XlatePen;
119
120 /* Translate the color to the target format */
121 iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crForegroundClr);
122
123 /* Update the eboText's solid color */
124 EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboText, iSolidColor);
125
126 /* Clear flag */
127 pdcattr->ulDirty_ &= ~DIRTY_TEXT;
128 }
129
130 VOID
131 FASTCALL
132 DC_vUpdateBackgroundBrush(PDC pdc)
133 {
134 PDC_ATTR pdcattr = pdc->pdcattr;
135 XLATEOBJ *pxlo;
136 ULONG iSolidColor;
137
138 /* ROS HACK, should use surf xlate */
139 pxlo = pdc->rosdc.XlatePen;
140
141 /* Translate the color to the target format */
142 iSolidColor = XLATEOBJ_iXlate(pxlo, pdcattr->crBackgroundClr);
143
144 /* Update the eboBackground's solid color */
145 EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboBackground, iSolidColor);
146
147 /* Clear flag */
148 pdcattr->ulDirty_ &= ~DIRTY_BACKGROUND;
149 }
150
151 HPALETTE
152 FASTCALL
153 GdiSelectPalette(
154 HDC hDC,
155 HPALETTE hpal,
156 BOOL ForceBackground)
157 {
158 PDC pdc;
159 HPALETTE oldPal = NULL;
160 PPALGDI ppal;
161
162 // FIXME: mark the palette as a [fore\back]ground pal
163 pdc = DC_LockDc(hDC);
164 if (!pdc)
165 {
166 return NULL;
167 }
168
169 /* Check if this is a valid palette handle */
170 ppal = PALETTE_LockPalette(hpal);
171 if (!ppal)
172 {
173 DC_UnlockDc(pdc);
174 return NULL;
175 }
176
177 /* Is this a valid palette for this depth? */
178 if ((pdc->rosdc.bitsPerPixel <= 8 && ppal->Mode == PAL_INDEXED) ||
179 (pdc->rosdc.bitsPerPixel > 8 && ppal->Mode != PAL_INDEXED))
180 {
181 oldPal = pdc->dclevel.hpal;
182 pdc->dclevel.hpal = hpal;
183 }
184 else if (pdc->rosdc.bitsPerPixel > 8 && ppal->Mode == PAL_INDEXED)
185 {
186 oldPal = pdc->dclevel.hpal;
187 pdc->dclevel.hpal = hpal;
188 }
189
190 PALETTE_UnlockPalette(ppal);
191 DC_UnlockDc(pdc);
192
193 return oldPal;
194 }
195
196 HBRUSH
197 FASTCALL
198 IntGdiSelectBrush(
199 PDC pDC,
200 HBRUSH hBrush)
201 {
202 PDC_ATTR pdcattr;
203 HBRUSH hOrgBrush;
204 PBRUSH pbrush;
205 XLATEOBJ *XlateObj;
206 BOOLEAN bFailed;
207
208 if (pDC == NULL || hBrush == NULL) return NULL;
209
210 pdcattr = pDC->pdcattr;
211
212 pbrush = BRUSH_LockBrush(hBrush);
213 if (pbrush == NULL)
214 {
215 SetLastWin32Error(ERROR_INVALID_HANDLE);
216 return NULL;
217 }
218
219 DC_vSelectFillBrush(pDC, pbrush);
220
221 XlateObj = IntGdiCreateBrushXlate(pDC, pbrush, &bFailed);
222 BRUSH_UnlockBrush(pbrush);
223 if(bFailed)
224 {
225 return NULL;
226 }
227
228 hOrgBrush = pdcattr->hbrush;
229 pdcattr->hbrush = hBrush;
230
231 if (pDC->rosdc.XlateBrush != NULL)
232 {
233 EngDeleteXlate(pDC->rosdc.XlateBrush);
234 }
235 pDC->rosdc.XlateBrush = XlateObj;
236
237 pdcattr->ulDirty_ &= ~DC_BRUSH_DIRTY;
238
239 return hOrgBrush;
240 }
241
242 HPEN
243 FASTCALL
244 IntGdiSelectPen(
245 PDC pDC,
246 HPEN hPen)
247 {
248 PDC_ATTR pdcattr;
249 HPEN hOrgPen = NULL;
250 PBRUSH pbrushPen;
251 XLATEOBJ *XlateObj;
252 BOOLEAN bFailed;
253
254 if (pDC == NULL || hPen == NULL) return NULL;
255
256 pdcattr = pDC->pdcattr;
257
258 pbrushPen = PEN_LockPen(hPen);
259 if (pbrushPen == NULL)
260 {
261 return NULL;
262 }
263
264 DC_vSelectLineBrush(pDC, pbrushPen);
265
266 XlateObj = IntGdiCreateBrushXlate(pDC, pbrushPen, &bFailed);
267 PEN_UnlockPen(pbrushPen);
268 if (bFailed)
269 {
270 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
271 return NULL;
272 }
273
274 hOrgPen = pdcattr->hpen;
275 pdcattr->hpen = hPen;
276
277 if (pDC->rosdc.XlatePen != NULL)
278 {
279 EngDeleteXlate(pDC->rosdc.XlatePen);
280 }
281 pdcattr->ulDirty_ &= ~DC_PEN_DIRTY;
282
283 pDC->rosdc.XlatePen = XlateObj;
284
285 return hOrgPen;
286 }
287
288
289 /*
290 * @implemented
291 */
292 HBRUSH
293 APIENTRY
294 NtGdiSelectBrush(
295 IN HDC hDC,
296 IN HBRUSH hBrush)
297 {
298 PDC pDC;
299 HBRUSH hOrgBrush;
300
301 if (hDC == NULL || hBrush == NULL) return NULL;
302
303 pDC = DC_LockDc(hDC);
304 if (!pDC)
305 {
306 return NULL;
307 }
308
309 hOrgBrush = IntGdiSelectBrush(pDC,hBrush);
310
311 DC_UnlockDc(pDC);
312
313 return hOrgBrush;
314 }
315
316 /*
317 * @implemented
318 */
319 HPEN
320 APIENTRY
321 NtGdiSelectPen(
322 IN HDC hDC,
323 IN HPEN hPen)
324 {
325 PDC pDC;
326 HPEN hOrgPen;
327
328 if (hDC == NULL || hPen == NULL) return NULL;
329
330 pDC = DC_LockDc(hDC);
331 if (!pDC)
332 {
333 return NULL;
334 }
335
336 hOrgPen = IntGdiSelectPen(pDC, hPen);
337
338 DC_UnlockDc(pDC);
339
340 return hOrgPen;
341 }
342
343 /*
344 * @implemented
345 */
346 HBITMAP
347 APIENTRY
348 NtGdiSelectBitmap(
349 IN HDC hDC,
350 IN HBITMAP hBmp)
351 {
352 PDC pDC;
353 PDC_ATTR pdcattr;
354 HBITMAP hOrgBmp;
355 PSURFACE psurfBmp, psurfOld;
356 HRGN hVisRgn;
357 BOOLEAN bFailed;
358 PBRUSH pbrush;
359
360 if (hDC == NULL || hBmp == NULL) return NULL;
361
362 pDC = DC_LockDc(hDC);
363 if (!pDC)
364 {
365 return NULL;
366 }
367 pdcattr = pDC->pdcattr;
368
369 /* must be memory dc to select bitmap */
370 if (pDC->dctype != DC_TYPE_MEMORY)
371 {
372 DC_UnlockDc(pDC);
373 return NULL;
374 }
375
376 psurfBmp = SURFACE_LockSurface(hBmp);
377 if (!psurfBmp)
378 {
379 DC_UnlockDc(pDC);
380 return NULL;
381 }
382
383 /* Get the handle for the old bitmap */
384 psurfOld = pDC->dclevel.pSurface;
385 hOrgBmp = psurfOld ? psurfOld->BaseObject.hHmgr : NULL;
386
387 /* FIXME: ros hack */
388 hOrgBmp = pDC->rosdc.hBitmap;
389
390 pDC->rosdc.hBitmap = hBmp;
391
392 /* Release the old bitmap, reference the new */
393 DC_vSelectSurface(pDC, psurfBmp);
394
395 // If Info DC this is zero and pSurface is moved to DC->pSurfInfo.
396 psurfBmp->hDC = hDC;
397
398 // if we're working with a DIB, get the palette
399 // [fixme: only create if the selected palette is null]
400 if (psurfBmp->hSecure)
401 {
402 // pDC->rosdc.bitsPerPixel = psurfBmp->dib->dsBmih.biBitCount; ???
403 pDC->rosdc.bitsPerPixel = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat);
404 }
405 else
406 {
407 pDC->rosdc.bitsPerPixel = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat);
408 }
409
410 /* FIXME; improve by using a region without a handle and selecting it */
411 hVisRgn = NtGdiCreateRectRgn(0,
412 0,
413 psurfBmp->SurfObj.sizlBitmap.cx,
414 psurfBmp->SurfObj.sizlBitmap.cy);
415
416 /* Release the exclusive lock */
417 SURFACE_UnlockSurface(psurfBmp);
418
419 /* Regenerate the XLATEOBJs. (hack!) */
420 pbrush = BRUSH_LockBrush(pdcattr->hbrush);
421 if (pbrush)
422 {
423 if (pDC->rosdc.XlateBrush)
424 {
425 EngDeleteXlate(pDC->rosdc.XlateBrush);
426 }
427 pDC->rosdc.XlateBrush = IntGdiCreateBrushXlate(pDC, pbrush, &bFailed);
428 BRUSH_UnlockBrush(pbrush);
429 }
430
431 pbrush = PEN_LockPen(pdcattr->hpen);
432 if (pbrush)
433 {
434 if (pDC->rosdc.XlatePen)
435 {
436 EngDeleteXlate(pDC->rosdc.XlatePen);
437 }
438 pDC->rosdc.XlatePen = IntGdiCreateBrushXlate(pDC, pbrush, &bFailed);
439 PEN_UnlockPen(pbrush);
440 }
441
442 DC_UnlockDc(pDC);
443
444 if (hVisRgn)
445 {
446 GdiSelectVisRgn(hDC, hVisRgn);
447 GreDeleteObject(hVisRgn);
448 }
449
450 return hOrgBmp;
451 }
452
453
454 BOOL
455 APIENTRY
456 NtGdiSelectClipPath(
457 HDC hDC,
458 int Mode)
459 {
460 HRGN hrgnPath;
461 PPATH pPath;
462 BOOL success = FALSE;
463 PDC_ATTR pdcattr;
464 PDC pdc;
465
466 pdc = DC_LockDc(hDC);
467 if (!pdc)
468 {
469 SetLastWin32Error(ERROR_INVALID_PARAMETER);
470 return FALSE;
471 }
472 pdcattr = pdc->pdcattr;
473
474 pPath = PATH_LockPath(pdc->dclevel.hPath);
475 if (!pPath)
476 {
477 DC_UnlockDc(pdc);
478 return FALSE;
479 }
480
481 /* Check that path is closed */
482 if (pPath->state != PATH_Closed)
483 {
484 SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
485 return FALSE;
486 }
487
488 /* Construct a region from the path */
489 else if (PATH_PathToRegion(pPath, pdcattr->jFillMode, &hrgnPath))
490 {
491 success = GdiExtSelectClipRgn(pdc, hrgnPath, Mode) != ERROR;
492 GreDeleteObject( hrgnPath );
493
494 /* Empty the path */
495 if (success)
496 PATH_EmptyPath(pPath);
497
498 /* FIXME: Should this function delete the path even if it failed? */
499 }
500
501 PATH_UnlockPath(pPath);
502 DC_UnlockDc(pdc);
503
504 return success;
505 }
506
507 HANDLE
508 APIENTRY
509 NtGdiGetDCObject(HDC hDC, INT ObjectType)
510 {
511 HGDIOBJ SelObject;
512 DC *pdc;
513 PDC_ATTR pdcattr;
514
515 /* From Wine: GetCurrentObject does not SetLastError() on a null object */
516 if(!hDC) return NULL;
517
518 if(!(pdc = DC_LockDc(hDC)))
519 {
520 SetLastWin32Error(ERROR_INVALID_HANDLE);
521 return NULL;
522 }
523 pdcattr = pdc->pdcattr;
524
525 if (pdcattr->ulDirty_ & DC_BRUSH_DIRTY)
526 IntGdiSelectBrush(pdc, pdcattr->hbrush);
527
528 if (pdcattr->ulDirty_ & DC_PEN_DIRTY)
529 IntGdiSelectPen(pdc, pdcattr->hpen);
530
531 switch(ObjectType)
532 {
533 case GDI_OBJECT_TYPE_EXTPEN:
534 case GDI_OBJECT_TYPE_PEN:
535 SelObject = pdcattr->hpen;
536 break;
537
538 case GDI_OBJECT_TYPE_BRUSH:
539 SelObject = pdcattr->hbrush;
540 break;
541
542 case GDI_OBJECT_TYPE_PALETTE:
543 SelObject = pdc->dclevel.hpal;
544 break;
545
546 case GDI_OBJECT_TYPE_FONT:
547 SelObject = pdcattr->hlfntNew;
548 break;
549
550 case GDI_OBJECT_TYPE_BITMAP:
551 SelObject = pdc->rosdc.hBitmap;
552 break;
553
554 case GDI_OBJECT_TYPE_COLORSPACE:
555 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
556 // SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ?
557 SelObject = NULL;
558 break;
559
560 default:
561 SelObject = NULL;
562 SetLastWin32Error(ERROR_INVALID_PARAMETER);
563 break;
564 }
565
566 DC_UnlockDc(pdc);
567 return SelObject;
568 }
569
570 ULONG
571 APIENTRY
572 NtGdiEnumObjects(
573 IN HDC hdc,
574 IN INT iObjectType,
575 IN ULONG cjBuf,
576 OUT OPTIONAL PVOID pvBuf)
577 {
578 UNIMPLEMENTED;
579 return 0;
580 }
581