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 PALETTE_ShareUnlockPalette(ppal
);
200 if (hDC
== NULL
|| hBrush
== NULL
) return NULL
;
202 pDC
= DC_LockDc(hDC
);
208 /* Simply return the user mode value, without checking */
209 hOrgBrush
= pDC
->pdcattr
->hbrush
;
210 pDC
->pdcattr
->hbrush
= hBrush
;
211 DC_vUpdateFillBrush(pDC
);
230 if (hDC
== NULL
|| hPen
== NULL
) return NULL
;
232 pDC
= DC_LockDc(hDC
);
238 /* Simply return the user mode value, without checking */
239 hOrgPen
= pDC
->pdcattr
->hpen
;
240 pDC
->pdcattr
->hpen
= hPen
;
241 DC_vUpdateLineBrush(pDC
);
260 PSURFACE psurfBmp
, psurfOld
;
263 if (hDC
== NULL
|| hBmp
== NULL
) return NULL
;
265 pDC
= DC_LockDc(hDC
);
270 pdcattr
= pDC
->pdcattr
;
272 /* must be memory dc to select bitmap */
273 if (pDC
->dctype
!= DC_TYPE_MEMORY
)
279 psurfBmp
= SURFACE_LockSurface(hBmp
);
286 /* Get the handle for the old bitmap */
287 ASSERT(pDC
->dclevel
.pSurface
);
288 hOrgBmp
= pDC
->dclevel
.pSurface
->BaseObject
.hHmgr
;
290 /* Lock it, to be sure while we mess with it*/
291 psurfOld
= SURFACE_LockSurface(hOrgBmp
);
293 /* Reset hdc, this surface isn't selected anymore */
294 psurfOld
->hdc
= NULL
;
296 /* Release the old bitmap, reference the new */
297 DC_vSelectSurface(pDC
, psurfBmp
);
299 /* And unlock it, now we're done */
300 SURFACE_UnlockSurface(psurfOld
);
302 // If Info DC this is zero and pSurface is moved to DC->pSurfInfo.
306 /* FIXME; improve by using a region without a handle and selecting it */
307 hVisRgn
= IntSysCreateRectRgn( 0,
309 psurfBmp
->SurfObj
.sizlBitmap
.cx
,
310 psurfBmp
->SurfObj
.sizlBitmap
.cy
);
312 if(psurfBmp
->hSecure
)
314 /* Set DIBSECTION attribute */
315 pdcattr
->ulDirty_
|= DC_DIBSECTION
;
319 pdcattr
->ulDirty_
&= ~DC_DIBSECTION
;
322 /* Release the exclusive lock */
323 SURFACE_UnlockSurface(psurfBmp
);
325 /* Mark the brushes invalid */
326 pdcattr
->ulDirty_
|= DIRTY_FILL
| DIRTY_LINE
;
332 GdiSelectVisRgn(hDC
, hVisRgn
);
333 REGION_FreeRgnByHandle(hVisRgn
);
348 BOOL success
= FALSE
;
352 pdc
= DC_LockDc(hDC
);
355 EngSetLastError(ERROR_INVALID_PARAMETER
);
358 pdcattr
= pdc
->pdcattr
;
360 pPath
= PATH_LockPath(pdc
->dclevel
.hPath
);
367 /* Check that path is closed */
368 if (pPath
->state
!= PATH_Closed
)
370 EngSetLastError(ERROR_CAN_NOT_COMPLETE
);
375 /* Construct a region from the path */
376 else if (PATH_PathToRegion(pPath
, pdcattr
->jFillMode
, &hrgnPath
))
378 success
= GdiExtSelectClipRgn(pdc
, hrgnPath
, Mode
) != ERROR
;
379 GreDeleteObject( hrgnPath
);
383 PATH_EmptyPath(pPath
);
385 /* FIXME: Should this function delete the path even if it failed? */
388 PATH_UnlockPath(pPath
);
396 NtGdiGetDCObject(HDC hDC
, INT ObjectType
)
402 /* From Wine: GetCurrentObject does not SetLastError() on a null object */
403 if(!hDC
) return NULL
;
405 if(!(pdc
= DC_LockDc(hDC
)))
407 EngSetLastError(ERROR_INVALID_HANDLE
);
410 pdcattr
= pdc
->pdcattr
;
412 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
413 DC_vUpdateFillBrush(pdc
);
415 if (pdcattr
->ulDirty_
& (DIRTY_LINE
| DC_PEN_DIRTY
))
416 DC_vUpdateLineBrush(pdc
);
420 case GDI_OBJECT_TYPE_EXTPEN
:
421 case GDI_OBJECT_TYPE_PEN
:
422 SelObject
= pdcattr
->hpen
;
425 case GDI_OBJECT_TYPE_BRUSH
:
426 SelObject
= pdcattr
->hbrush
;
429 case GDI_OBJECT_TYPE_PALETTE
:
430 SelObject
= pdc
->dclevel
.hpal
;
433 case GDI_OBJECT_TYPE_FONT
:
434 SelObject
= pdcattr
->hlfntNew
;
437 case GDI_OBJECT_TYPE_BITMAP
:
439 SURFACE
*psurf
= pdc
->dclevel
.pSurface
;
440 SelObject
= psurf
? psurf
->BaseObject
.hHmgr
: NULL
;
444 case GDI_OBJECT_TYPE_COLORSPACE
:
445 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
446 // SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ?
452 EngSetLastError(ERROR_INVALID_PARAMETER
);
460 /* See wine, msdn, osr and Feng Yuan - Windows Graphics Programming Win32 Gdi And Directdraw
462 1st: http://www.codeproject.com/gdi/cliprgnguide.asp is wrong!
464 The intersection of the clip with the meta region is not Rao it's API!
465 Go back and read 7.2 Clipping pages 418-19:
467 1) The Rao region is the intersection of the API region and the system region,
468 named after the Microsoft engineer who initially proposed it.
469 2) The Rao region can be calculated from the API region and the system region.
472 API region is the intersection of the meta region and the clipping region,
473 clearly named after the fact that it is controlled by GDI API calls.
487 pdc
= DC_LockDc(hdc
);
490 EngSetLastError(ERROR_INVALID_HANDLE
);
497 hrgnSrc
= pdc
->rosdc
.hClipRgn
;
498 // if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr;
501 if (pdc
->dclevel
.prgnMeta
)
502 hrgnSrc
= pdc
->dclevel
.prgnMeta
->BaseObject
.hHmgr
;
505 if (pdc
->prgnAPI
) hrgnSrc
= pdc
->prgnAPI
->BaseObject
.hHmgr
;
506 // else if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr;
507 else if (pdc
->rosdc
.hClipRgn
) hrgnSrc
= pdc
->rosdc
.hClipRgn
;
508 else if (pdc
->dclevel
.prgnMeta
) hrgnSrc
= pdc
->dclevel
.prgnMeta
->BaseObject
.hHmgr
;
511 if (pdc
->prgnVis
) hrgnSrc
= pdc
->prgnVis
->BaseObject
.hHmgr
;
519 ret
= NtGdiCombineRgn(hrgnDest
, hrgnSrc
, 0, RGN_COPY
) == ERROR
? -1 : 1;
524 ptlOrg
= pdc
->ptlDCOrig
;
525 NtGdiOffsetRgn(hrgnDest
, ptlOrg
.x
, ptlOrg
.y
);
539 OUT OPTIONAL PVOID pvBuf
)