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)
16 DC_vUpdateFillBrush(PDC pdc
)
18 PDC_ATTR pdcattr
= pdc
->pdcattr
;
21 /* Check if the brush handle has changed */
22 if (pdcattr
->hbrush
!= pdc
->dclevel
.pbrFill
->BaseObject
.hHmgr
)
24 /* Try to lock the new brush */
25 pbrFill
= BRUSH_ShareLockBrush(pdcattr
->hbrush
);
28 /* Unlock old brush, set new brush */
29 BRUSH_ShareUnlockBrush(pdc
->dclevel
.pbrFill
);
30 pdc
->dclevel
.pbrFill
= pbrFill
;
32 /* Mark eboFill as dirty */
33 pdcattr
->ulDirty_
|= DIRTY_FILL
;
37 /* Invalid brush handle, restore old one */
38 pdcattr
->hbrush
= pdc
->dclevel
.pbrFill
->BaseObject
.hHmgr
;
42 /* Check if the EBRUSHOBJ needs update */
43 if (pdcattr
->ulDirty_
& DIRTY_FILL
)
46 EBRUSHOBJ_vUpdate(&pdc
->eboFill
, pdc
->dclevel
.pbrFill
, pdc
);
49 /* Check for DC brush */
50 if (pdcattr
->hbrush
== StockObjects
[DC_BRUSH
])
52 /* ROS HACK, should use surf xlate */
53 /* Update the eboFill's solid color */
54 EBRUSHOBJ_vSetSolidBrushColor(&pdc
->eboFill
, pdcattr
->crPenClr
);
58 pdcattr
->ulDirty_
&= ~(DIRTY_FILL
| DC_BRUSH_DIRTY
);
63 DC_vUpdateLineBrush(PDC pdc
)
65 PDC_ATTR pdcattr
= pdc
->pdcattr
;
68 /* Check if the pen handle has changed */
69 if (pdcattr
->hpen
!= pdc
->dclevel
.pbrLine
->BaseObject
.hHmgr
)
71 /* Try to lock the new pen */
72 pbrLine
= PEN_ShareLockPen(pdcattr
->hpen
);
75 /* Unlock old brush, set new brush */
76 BRUSH_ShareUnlockBrush(pdc
->dclevel
.pbrLine
);
77 pdc
->dclevel
.pbrLine
= pbrLine
;
79 /* Mark eboLine as dirty */
80 pdcattr
->ulDirty_
|= DIRTY_LINE
;
84 /* Invalid pen handle, restore old one */
85 pdcattr
->hpen
= pdc
->dclevel
.pbrLine
->BaseObject
.hHmgr
;
89 /* Check if the EBRUSHOBJ needs update */
90 if (pdcattr
->ulDirty_
& DIRTY_LINE
)
93 EBRUSHOBJ_vUpdate(&pdc
->eboLine
, pdc
->dclevel
.pbrLine
, pdc
);
96 /* Check for DC pen */
97 if (pdcattr
->hpen
== StockObjects
[DC_PEN
])
99 /* Update the eboLine's solid color */
100 EBRUSHOBJ_vSetSolidBrushColor(&pdc
->eboLine
, pdcattr
->crPenClr
);
104 pdcattr
->ulDirty_
&= ~(DIRTY_LINE
| DC_PEN_DIRTY
);
109 DC_vUpdateTextBrush(PDC pdc
)
111 PDC_ATTR pdcattr
= pdc
->pdcattr
;
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
);
118 /* Update the eboText's solid color */
119 EBRUSHOBJ_vSetSolidBrushColor(&pdc
->eboText
, pdcattr
->crForegroundClr
);
122 pdcattr
->ulDirty_
&= ~DIRTY_TEXT
;
127 DC_vUpdateBackgroundBrush(PDC pdc
)
129 PDC_ATTR pdcattr
= pdc
->pdcattr
;
131 if(pdcattr
->ulDirty_
& DIRTY_BACKGROUND
)
132 EBRUSHOBJ_vUpdate(&pdc
->eboBackground
, pbrDefaultBrush
, pdc
);
134 /* Update the eboBackground's solid color */
135 EBRUSHOBJ_vSetSolidBrushColor(&pdc
->eboBackground
, pdcattr
->crBackgroundClr
);
138 pdcattr
->ulDirty_
&= ~DIRTY_BACKGROUND
;
146 BOOL ForceBackground
)
149 HPALETTE oldPal
= NULL
;
152 // FIXME: mark the palette as a [fore\back]ground pal
153 pdc
= DC_LockDc(hDC
);
159 /* Check if this is a valid palette handle */
160 ppal
= PALETTE_ShareLockPalette(hpal
);
167 /* Is this a valid palette for this depth? */
168 if ((BitsPerFormat(pdc
->dclevel
.pSurface
->SurfObj
.iBitmapFormat
) <= 8
169 && (ppal
->flFlags
& PAL_INDEXED
)) ||
170 (BitsPerFormat(pdc
->dclevel
.pSurface
->SurfObj
.iBitmapFormat
) > 8))
172 /* Get old palette, set new one */
173 oldPal
= pdc
->dclevel
.hpal
;
174 pdc
->dclevel
.hpal
= hpal
;
175 DC_vSelectPalette(pdc
, ppal
);
177 /* Mark the brushes invalid */
178 pdc
->pdcattr
->ulDirty_
|= DIRTY_FILL
| DIRTY_LINE
|
179 DIRTY_BACKGROUND
| DIRTY_TEXT
;
182 if(pdc
->dctype
== DCTYPE_MEMORY
)
184 // This didn't work anyway
185 //IntGdiRealizePalette(hDC);
188 PALETTE_ShareUnlockPalette(ppal
);
206 if (hDC
== NULL
|| hBrush
== NULL
) return NULL
;
208 pDC
= DC_LockDc(hDC
);
214 /* Simply return the user mode value, without checking */
215 hOrgBrush
= pDC
->pdcattr
->hbrush
;
216 pDC
->pdcattr
->hbrush
= hBrush
;
217 DC_vUpdateFillBrush(pDC
);
236 if (hDC
== NULL
|| hPen
== NULL
) return NULL
;
238 pDC
= DC_LockDc(hDC
);
244 /* Simply return the user mode value, without checking */
245 hOrgPen
= pDC
->pdcattr
->hpen
;
246 pDC
->pdcattr
->hpen
= hPen
;
247 DC_vUpdateLineBrush(pDC
);
268 SIZEL sizlBitmap
= {1, 1};
272 /* Verify parameters */
273 if (hdc
== NULL
|| hbmp
== NULL
) return NULL
;
275 /* First lock the DC */
276 pdc
= DC_LockDc(hdc
);
281 pdcattr
= pdc
->pdcattr
;
283 /* Must be a memory dc to select a bitmap */
284 if (pdc
->dctype
!= DC_TYPE_MEMORY
)
290 /* Check if there was a bitmap selected before */
291 if (pdc
->dclevel
.pSurface
)
293 /* Return its handle */
294 hbmpOld
= pdc
->dclevel
.pSurface
->BaseObject
.hHmgr
;
298 /* Return default bitmap */
299 hbmpOld
= StockObjects
[DEFAULT_BITMAP
];
302 /* Check if the default bitmap was passed */
303 if (hbmp
== StockObjects
[DEFAULT_BITMAP
])
308 psurfNew
= SURFACE_ShareLockSurface(hbmp
);
312 /* Reference the new bitmap and check if it's valid */
313 psurfNew
= SURFACE_ShareLockSurface(hbmp
);
320 /* Set the bitmp's hdc */
321 hdcOld
= InterlockedCompareExchangePointer((PVOID
*)&psurfNew
->hdc
, hdc
, 0);
322 if (hdcOld
!= NULL
&& hdcOld
!= hdc
)
324 /* The bitmap is already selected, fail */
325 SURFACE_ShareUnlockSurface(psurfNew
);
330 /* Get the bitmap size */
331 sizlBitmap
= psurfNew
->SurfObj
.sizlBitmap
;
333 /* Check if the bitmap is a dibsection */
334 if(psurfNew
->hSecure
)
336 /* Set DIBSECTION attribute */
337 pdcattr
->ulDirty_
|= DC_DIBSECTION
;
341 pdcattr
->ulDirty_
&= ~DC_DIBSECTION
;
345 /* Select the new surface, release the old */
346 DC_vSelectSurface(pdc
, psurfNew
);
348 /* Set the new size */
349 pdc
->dclevel
.sizl
= sizlBitmap
;
351 /* Release one reference we added */
352 SURFACE_ShareUnlockSurface(psurfNew
);
354 /* Mark the dc brushes invalid */
355 pdcattr
->ulDirty_
|= DIRTY_FILL
| DIRTY_LINE
;
360 /* FIXME; improve by using a region without a handle and selecting it */
361 hVisRgn
= IntSysCreateRectRgn( 0,
367 GdiSelectVisRgn(hdc
, hVisRgn
);
368 GreDeleteObject(hVisRgn
);
371 /* Return the old bitmap handle */
384 BOOL success
= FALSE
;
388 pdc
= DC_LockDc(hDC
);
391 EngSetLastError(ERROR_INVALID_PARAMETER
);
394 pdcattr
= pdc
->pdcattr
;
396 pPath
= PATH_LockPath(pdc
->dclevel
.hPath
);
403 /* Check that path is closed */
404 if (pPath
->state
!= PATH_Closed
)
406 EngSetLastError(ERROR_CAN_NOT_COMPLETE
);
411 /* Construct a region from the path */
412 else if (PATH_PathToRegion(pPath
, pdcattr
->jFillMode
, &hrgnPath
))
414 success
= GdiExtSelectClipRgn(pdc
, hrgnPath
, Mode
) != ERROR
;
415 GreDeleteObject( hrgnPath
);
419 PATH_EmptyPath(pPath
);
421 /* FIXME: Should this function delete the path even if it failed? */
424 PATH_UnlockPath(pPath
);
432 NtGdiGetDCObject(HDC hDC
, INT ObjectType
)
438 /* From Wine: GetCurrentObject does not SetLastError() on a null object */
439 if(!hDC
) return NULL
;
441 if(!(pdc
= DC_LockDc(hDC
)))
443 EngSetLastError(ERROR_INVALID_HANDLE
);
446 pdcattr
= pdc
->pdcattr
;
448 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
449 DC_vUpdateFillBrush(pdc
);
451 if (pdcattr
->ulDirty_
& (DIRTY_LINE
| DC_PEN_DIRTY
))
452 DC_vUpdateLineBrush(pdc
);
456 case GDI_OBJECT_TYPE_EXTPEN
:
457 case GDI_OBJECT_TYPE_PEN
:
458 SelObject
= pdcattr
->hpen
;
461 case GDI_OBJECT_TYPE_BRUSH
:
462 SelObject
= pdcattr
->hbrush
;
465 case GDI_OBJECT_TYPE_PALETTE
:
466 SelObject
= pdc
->dclevel
.hpal
;
469 case GDI_OBJECT_TYPE_FONT
:
470 SelObject
= pdcattr
->hlfntNew
;
473 case GDI_OBJECT_TYPE_BITMAP
:
475 SURFACE
*psurf
= pdc
->dclevel
.pSurface
;
476 SelObject
= psurf
? psurf
->BaseObject
.hHmgr
: NULL
;
480 case GDI_OBJECT_TYPE_COLORSPACE
:
481 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
482 // SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ?
488 EngSetLastError(ERROR_INVALID_PARAMETER
);
496 /* See wine, msdn, osr and Feng Yuan - Windows Graphics Programming Win32 Gdi And Directdraw
498 1st: http://www.codeproject.com/gdi/cliprgnguide.asp is wrong!
500 The intersection of the clip with the meta region is not Rao it's API!
501 Go back and read 7.2 Clipping pages 418-19:
503 1) The Rao region is the intersection of the API region and the system region,
504 named after the Microsoft engineer who initially proposed it.
505 2) The Rao region can be calculated from the API region and the system region.
508 API region is the intersection of the meta region and the clipping region,
509 clearly named after the fact that it is controlled by GDI API calls.
523 pdc
= DC_LockDc(hdc
);
526 EngSetLastError(ERROR_INVALID_PARAMETER
);
533 hrgnSrc
= pdc
->rosdc
.hClipRgn
;
534 // if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr;
537 if (pdc
->dclevel
.prgnMeta
)
538 hrgnSrc
= pdc
->dclevel
.prgnMeta
->BaseObject
.hHmgr
;
541 if (pdc
->prgnAPI
) hrgnSrc
= pdc
->prgnAPI
->BaseObject
.hHmgr
;
542 // else if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr;
543 else if (pdc
->rosdc
.hClipRgn
) hrgnSrc
= pdc
->rosdc
.hClipRgn
;
544 else if (pdc
->dclevel
.prgnMeta
) hrgnSrc
= pdc
->dclevel
.prgnMeta
->BaseObject
.hHmgr
;
549 PREGION prgnDest
= REGION_LockRgn(hrgnDest
);
550 ret
= IntGdiCombineRgn(prgnDest
, pdc
->prgnVis
, 0, RGN_COPY
) == ERROR
? -1 : 1;
551 REGION_UnlockRgn(prgnDest
);
560 ret
= NtGdiCombineRgn(hrgnDest
, hrgnSrc
, 0, RGN_COPY
) == ERROR
? -1 : 1;
565 ptlOrg
= pdc
->ptlDCOrig
;
566 NtGdiOffsetRgn(hrgnDest
, ptlOrg
.x
, ptlOrg
.y
);
580 OUT OPTIONAL PVOID pvBuf
)