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 IntGdiRealizePalette(pdc
);
187 PALETTE_ShareUnlockPalette(ppal
);
205 if (hDC
== NULL
|| hBrush
== NULL
) return NULL
;
207 pDC
= DC_LockDc(hDC
);
213 /* Simply return the user mode value, without checking */
214 hOrgBrush
= pDC
->pdcattr
->hbrush
;
215 pDC
->pdcattr
->hbrush
= hBrush
;
216 DC_vUpdateFillBrush(pDC
);
235 if (hDC
== NULL
|| hPen
== NULL
) return NULL
;
237 pDC
= DC_LockDc(hDC
);
243 /* Simply return the user mode value, without checking */
244 hOrgPen
= pDC
->pdcattr
->hpen
;
245 pDC
->pdcattr
->hpen
= hPen
;
246 DC_vUpdateLineBrush(pDC
);
267 SIZEL sizlBitmap
= {1, 1};
271 /* Verify parameters */
272 if (hdc
== NULL
|| hbmp
== NULL
) return NULL
;
274 /* First lock the DC */
275 pdc
= DC_LockDc(hdc
);
280 pdcattr
= pdc
->pdcattr
;
282 /* Must be a memory dc to select a bitmap */
283 if (pdc
->dctype
!= DC_TYPE_MEMORY
)
289 /* Check if there was a bitmap selected before */
290 if (pdc
->dclevel
.pSurface
)
292 /* Return its handle */
293 hbmpOld
= pdc
->dclevel
.pSurface
->BaseObject
.hHmgr
;
297 /* Return default bitmap */
298 hbmpOld
= StockObjects
[DEFAULT_BITMAP
];
301 /* Check if the default bitmap was passed */
302 if (hbmp
== StockObjects
[DEFAULT_BITMAP
])
307 psurfNew
= SURFACE_ShareLockSurface(hbmp
);
311 /* Reference the new bitmap and check if it's valid */
312 psurfNew
= SURFACE_ShareLockSurface(hbmp
);
319 /* Set the bitmp's hdc */
320 hdcOld
= InterlockedCompareExchangePointer((PVOID
*)&psurfNew
->hdc
, hdc
, 0);
321 if (hdcOld
!= NULL
&& hdcOld
!= hdc
)
323 /* The bitmap is already selected, fail */
324 SURFACE_ShareUnlockSurface(psurfNew
);
329 /* Get the bitmap size */
330 sizlBitmap
= psurfNew
->SurfObj
.sizlBitmap
;
332 /* Check if the bitmap is a dibsection */
333 if(psurfNew
->hSecure
)
335 /* Set DIBSECTION attribute */
336 pdcattr
->ulDirty_
|= DC_DIBSECTION
;
340 pdcattr
->ulDirty_
&= ~DC_DIBSECTION
;
344 /* Select the new surface, release the old */
345 DC_vSelectSurface(pdc
, psurfNew
);
347 /* Set the new size */
348 pdc
->dclevel
.sizl
= sizlBitmap
;
350 /* Release one reference we added */
351 SURFACE_ShareUnlockSurface(psurfNew
);
353 /* Mark the dc brushes invalid */
354 pdcattr
->ulDirty_
|= DIRTY_FILL
| DIRTY_LINE
;
359 /* FIXME; improve by using a region without a handle and selecting it */
360 hVisRgn
= IntSysCreateRectRgn( 0,
366 GdiSelectVisRgn(hdc
, hVisRgn
);
367 REGION_FreeRgnByHandle(hVisRgn
);
370 /* Return the old bitmap handle */
383 BOOL success
= FALSE
;
387 pdc
= DC_LockDc(hDC
);
390 EngSetLastError(ERROR_INVALID_PARAMETER
);
393 pdcattr
= pdc
->pdcattr
;
395 pPath
= PATH_LockPath(pdc
->dclevel
.hPath
);
402 /* Check that path is closed */
403 if (pPath
->state
!= PATH_Closed
)
405 EngSetLastError(ERROR_CAN_NOT_COMPLETE
);
410 /* Construct a region from the path */
411 else if (PATH_PathToRegion(pPath
, pdcattr
->jFillMode
, &hrgnPath
))
413 success
= GdiExtSelectClipRgn(pdc
, hrgnPath
, Mode
) != ERROR
;
414 GreDeleteObject( hrgnPath
);
418 PATH_EmptyPath(pPath
);
420 /* FIXME: Should this function delete the path even if it failed? */
423 PATH_UnlockPath(pPath
);
431 NtGdiGetDCObject(HDC hDC
, INT ObjectType
)
437 /* From Wine: GetCurrentObject does not SetLastError() on a null object */
438 if(!hDC
) return NULL
;
440 if(!(pdc
= DC_LockDc(hDC
)))
442 EngSetLastError(ERROR_INVALID_HANDLE
);
445 pdcattr
= pdc
->pdcattr
;
447 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
448 DC_vUpdateFillBrush(pdc
);
450 if (pdcattr
->ulDirty_
& (DIRTY_LINE
| DC_PEN_DIRTY
))
451 DC_vUpdateLineBrush(pdc
);
455 case GDI_OBJECT_TYPE_EXTPEN
:
456 case GDI_OBJECT_TYPE_PEN
:
457 SelObject
= pdcattr
->hpen
;
460 case GDI_OBJECT_TYPE_BRUSH
:
461 SelObject
= pdcattr
->hbrush
;
464 case GDI_OBJECT_TYPE_PALETTE
:
465 SelObject
= pdc
->dclevel
.hpal
;
468 case GDI_OBJECT_TYPE_FONT
:
469 SelObject
= pdcattr
->hlfntNew
;
472 case GDI_OBJECT_TYPE_BITMAP
:
474 SURFACE
*psurf
= pdc
->dclevel
.pSurface
;
475 SelObject
= psurf
? psurf
->BaseObject
.hHmgr
: NULL
;
479 case GDI_OBJECT_TYPE_COLORSPACE
:
480 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
481 // SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ?
487 EngSetLastError(ERROR_INVALID_PARAMETER
);
495 /* See wine, msdn, osr and Feng Yuan - Windows Graphics Programming Win32 Gdi And Directdraw
497 1st: http://www.codeproject.com/gdi/cliprgnguide.asp is wrong!
499 The intersection of the clip with the meta region is not Rao it's API!
500 Go back and read 7.2 Clipping pages 418-19:
502 1) The Rao region is the intersection of the API region and the system region,
503 named after the Microsoft engineer who initially proposed it.
504 2) The Rao region can be calculated from the API region and the system region.
507 API region is the intersection of the meta region and the clipping region,
508 clearly named after the fact that it is controlled by GDI API calls.
522 pdc
= DC_LockDc(hdc
);
525 EngSetLastError(ERROR_INVALID_PARAMETER
);
532 hrgnSrc
= pdc
->rosdc
.hClipRgn
;
533 // if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr;
536 if (pdc
->dclevel
.prgnMeta
)
537 hrgnSrc
= pdc
->dclevel
.prgnMeta
->BaseObject
.hHmgr
;
540 if (pdc
->prgnAPI
) hrgnSrc
= pdc
->prgnAPI
->BaseObject
.hHmgr
;
541 // else if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr;
542 else if (pdc
->rosdc
.hClipRgn
) hrgnSrc
= pdc
->rosdc
.hClipRgn
;
543 else if (pdc
->dclevel
.prgnMeta
) hrgnSrc
= pdc
->dclevel
.prgnMeta
->BaseObject
.hHmgr
;
546 if (pdc
->prgnVis
) hrgnSrc
= pdc
->prgnVis
->BaseObject
.hHmgr
;
554 ret
= NtGdiCombineRgn(hrgnDest
, hrgnSrc
, 0, RGN_COPY
) == ERROR
? -1 : 1;
559 ptlOrg
= pdc
->ptlDCOrig
;
560 NtGdiOffsetRgn(hrgnDest
, ptlOrg
.x
, ptlOrg
.y
);
574 OUT OPTIONAL PVOID pvBuf
)