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
);
262 SIZEL sizlBitmap
= {1, 1};
266 /* Verify parameters */
267 if (hdc
== NULL
|| hbmp
== NULL
) return NULL
;
269 /* First lock the DC */
270 pdc
= DC_LockDc(hdc
);
275 pdcattr
= pdc
->pdcattr
;
277 /* Must be a memory dc to select a bitmap */
278 if (pdc
->dctype
!= DC_TYPE_MEMORY
)
284 /* Check if there was a bitmap selected before */
285 if (pdc
->dclevel
.pSurface
)
287 /* Return its handle */
288 hbmpOld
= pdc
->dclevel
.pSurface
->BaseObject
.hHmgr
;
292 /* Return default bitmap */
293 hbmpOld
= StockObjects
[DEFAULT_BITMAP
];
296 /* Check if the default bitmap was passed */
297 if (hbmp
== StockObjects
[DEFAULT_BITMAP
])
302 psurfNew
= SURFACE_ShareLockSurface(hbmp
);
306 /* Reference the new bitmap and check if it's valid */
307 psurfNew
= SURFACE_ShareLockSurface(hbmp
);
314 /* Set the bitmp's hdc */
315 hdcOld
= InterlockedCompareExchangePointer((PVOID
*)&psurfNew
->hdc
, hdc
, 0);
316 if (hdcOld
!= NULL
&& hdcOld
!= hdc
)
318 /* The bitmap is already selected, fail */
319 SURFACE_ShareUnlockSurface(psurfNew
);
324 /* Get the bitmap size */
325 sizlBitmap
= psurfNew
->SurfObj
.sizlBitmap
;
327 /* Check if the bitmap is a dibsection */
328 if(psurfNew
->hSecure
)
330 /* Set DIBSECTION attribute */
331 pdcattr
->ulDirty_
|= DC_DIBSECTION
;
335 pdcattr
->ulDirty_
&= ~DC_DIBSECTION
;
339 /* Select the new surface, release the old */
340 DC_vSelectSurface(pdc
, psurfNew
);
342 /* Set the new size */
343 pdc
->dclevel
.sizl
= sizlBitmap
;
345 /* Release one reference we added */
346 SURFACE_ShareUnlockSurface(psurfNew
);
348 /* Mark the dc brushes invalid */
349 pdcattr
->ulDirty_
|= DIRTY_FILL
| DIRTY_LINE
;
354 /* FIXME; improve by using a region without a handle and selecting it */
355 hVisRgn
= IntSysCreateRectRgn( 0,
361 GdiSelectVisRgn(hdc
, hVisRgn
);
362 REGION_FreeRgnByHandle(hVisRgn
);
365 /* Return the old bitmp handle */
378 BOOL success
= FALSE
;
382 pdc
= DC_LockDc(hDC
);
385 EngSetLastError(ERROR_INVALID_PARAMETER
);
388 pdcattr
= pdc
->pdcattr
;
390 pPath
= PATH_LockPath(pdc
->dclevel
.hPath
);
397 /* Check that path is closed */
398 if (pPath
->state
!= PATH_Closed
)
400 EngSetLastError(ERROR_CAN_NOT_COMPLETE
);
405 /* Construct a region from the path */
406 else if (PATH_PathToRegion(pPath
, pdcattr
->jFillMode
, &hrgnPath
))
408 success
= GdiExtSelectClipRgn(pdc
, hrgnPath
, Mode
) != ERROR
;
409 GreDeleteObject( hrgnPath
);
413 PATH_EmptyPath(pPath
);
415 /* FIXME: Should this function delete the path even if it failed? */
418 PATH_UnlockPath(pPath
);
426 NtGdiGetDCObject(HDC hDC
, INT ObjectType
)
432 /* From Wine: GetCurrentObject does not SetLastError() on a null object */
433 if(!hDC
) return NULL
;
435 if(!(pdc
= DC_LockDc(hDC
)))
437 EngSetLastError(ERROR_INVALID_HANDLE
);
440 pdcattr
= pdc
->pdcattr
;
442 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
443 DC_vUpdateFillBrush(pdc
);
445 if (pdcattr
->ulDirty_
& (DIRTY_LINE
| DC_PEN_DIRTY
))
446 DC_vUpdateLineBrush(pdc
);
450 case GDI_OBJECT_TYPE_EXTPEN
:
451 case GDI_OBJECT_TYPE_PEN
:
452 SelObject
= pdcattr
->hpen
;
455 case GDI_OBJECT_TYPE_BRUSH
:
456 SelObject
= pdcattr
->hbrush
;
459 case GDI_OBJECT_TYPE_PALETTE
:
460 SelObject
= pdc
->dclevel
.hpal
;
463 case GDI_OBJECT_TYPE_FONT
:
464 SelObject
= pdcattr
->hlfntNew
;
467 case GDI_OBJECT_TYPE_BITMAP
:
469 SURFACE
*psurf
= pdc
->dclevel
.pSurface
;
470 SelObject
= psurf
? psurf
->BaseObject
.hHmgr
: NULL
;
474 case GDI_OBJECT_TYPE_COLORSPACE
:
475 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
476 // SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ?
482 EngSetLastError(ERROR_INVALID_PARAMETER
);
490 /* See wine, msdn, osr and Feng Yuan - Windows Graphics Programming Win32 Gdi And Directdraw
492 1st: http://www.codeproject.com/gdi/cliprgnguide.asp is wrong!
494 The intersection of the clip with the meta region is not Rao it's API!
495 Go back and read 7.2 Clipping pages 418-19:
497 1) The Rao region is the intersection of the API region and the system region,
498 named after the Microsoft engineer who initially proposed it.
499 2) The Rao region can be calculated from the API region and the system region.
502 API region is the intersection of the meta region and the clipping region,
503 clearly named after the fact that it is controlled by GDI API calls.
517 pdc
= DC_LockDc(hdc
);
520 EngSetLastError(ERROR_INVALID_HANDLE
);
527 hrgnSrc
= pdc
->rosdc
.hClipRgn
;
528 // if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr;
531 if (pdc
->dclevel
.prgnMeta
)
532 hrgnSrc
= pdc
->dclevel
.prgnMeta
->BaseObject
.hHmgr
;
535 if (pdc
->prgnAPI
) hrgnSrc
= pdc
->prgnAPI
->BaseObject
.hHmgr
;
536 // else if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr;
537 else if (pdc
->rosdc
.hClipRgn
) hrgnSrc
= pdc
->rosdc
.hClipRgn
;
538 else if (pdc
->dclevel
.prgnMeta
) hrgnSrc
= pdc
->dclevel
.prgnMeta
->BaseObject
.hHmgr
;
541 if (pdc
->prgnVis
) hrgnSrc
= pdc
->prgnVis
->BaseObject
.hHmgr
;
549 ret
= NtGdiCombineRgn(hrgnDest
, hrgnSrc
, 0, RGN_COPY
) == ERROR
? -1 : 1;
554 ptlOrg
= pdc
->ptlDCOrig
;
555 NtGdiOffsetRgn(hrgnDest
, ptlOrg
.x
, ptlOrg
.y
);
569 OUT OPTIONAL PVOID pvBuf
)