Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendcobjs.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Win32k subsystem 00004 * PURPOSE: Functions for creation and destruction of DCs 00005 * FILE: subsystems/win32/win32k/objects/dcobjs.c 00006 * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org) 00007 */ 00008 00009 #include <win32k.h> 00010 00011 #define NDEBUG 00012 #include <debug.h> 00013 00014 VOID 00015 FASTCALL 00016 DC_vUpdateFillBrush(PDC pdc) 00017 { 00018 PDC_ATTR pdcattr = pdc->pdcattr; 00019 PBRUSH pbrFill; 00020 00021 /* Check if the brush handle has changed */ 00022 if (pdcattr->hbrush != pdc->dclevel.pbrFill->BaseObject.hHmgr) 00023 { 00024 /* Try to lock the new brush */ 00025 pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush); 00026 if (pbrFill) 00027 { 00028 /* Unlock old brush, set new brush */ 00029 BRUSH_ShareUnlockBrush(pdc->dclevel.pbrFill); 00030 pdc->dclevel.pbrFill = pbrFill; 00031 00032 /* Mark eboFill as dirty */ 00033 pdcattr->ulDirty_ |= DIRTY_FILL; 00034 } 00035 else 00036 { 00037 /* Invalid brush handle, restore old one */ 00038 pdcattr->hbrush = pdc->dclevel.pbrFill->BaseObject.hHmgr; 00039 } 00040 } 00041 00042 /* Check if the EBRUSHOBJ needs update */ 00043 if (pdcattr->ulDirty_ & DIRTY_FILL) 00044 { 00045 /* Update eboFill */ 00046 EBRUSHOBJ_vUpdate(&pdc->eboFill, pdc->dclevel.pbrFill, pdc); 00047 } 00048 00049 /* Check for DC brush */ 00050 if (pdcattr->hbrush == StockObjects[DC_BRUSH]) 00051 { 00052 /* ROS HACK, should use surf xlate */ 00053 /* Update the eboFill's solid color */ 00054 EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboFill, pdcattr->crPenClr); 00055 } 00056 00057 /* Clear flags */ 00058 pdcattr->ulDirty_ &= ~(DIRTY_FILL | DC_BRUSH_DIRTY); 00059 } 00060 00061 VOID 00062 FASTCALL 00063 DC_vUpdateLineBrush(PDC pdc) 00064 { 00065 PDC_ATTR pdcattr = pdc->pdcattr; 00066 PBRUSH pbrLine; 00067 00068 /* Check if the pen handle has changed */ 00069 if (pdcattr->hpen != pdc->dclevel.pbrLine->BaseObject.hHmgr) 00070 { 00071 /* Try to lock the new pen */ 00072 pbrLine = PEN_ShareLockPen(pdcattr->hpen); 00073 if (pbrLine) 00074 { 00075 /* Unlock old brush, set new brush */ 00076 BRUSH_ShareUnlockBrush(pdc->dclevel.pbrLine); 00077 pdc->dclevel.pbrLine = pbrLine; 00078 00079 /* Mark eboLine as dirty */ 00080 pdcattr->ulDirty_ |= DIRTY_LINE; 00081 } 00082 else 00083 { 00084 /* Invalid pen handle, restore old one */ 00085 pdcattr->hpen = pdc->dclevel.pbrLine->BaseObject.hHmgr; 00086 } 00087 } 00088 00089 /* Check if the EBRUSHOBJ needs update */ 00090 if (pdcattr->ulDirty_ & DIRTY_LINE) 00091 { 00092 /* Update eboLine */ 00093 EBRUSHOBJ_vUpdate(&pdc->eboLine, pdc->dclevel.pbrLine, pdc); 00094 } 00095 00096 /* Check for DC pen */ 00097 if (pdcattr->hpen == StockObjects[DC_PEN]) 00098 { 00099 /* Update the eboLine's solid color */ 00100 EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboLine, pdcattr->crPenClr); 00101 } 00102 00103 /* Clear flags */ 00104 pdcattr->ulDirty_ &= ~(DIRTY_LINE | DC_PEN_DIRTY); 00105 } 00106 00107 VOID 00108 FASTCALL 00109 DC_vUpdateTextBrush(PDC pdc) 00110 { 00111 PDC_ATTR pdcattr = pdc->pdcattr; 00112 00113 /* Timo : The text brush should never be changed. 00114 * Jérôme : Yeah, but its palette must be updated anyway! */ 00115 if(pdcattr->ulDirty_ & DIRTY_TEXT) 00116 EBRUSHOBJ_vUpdate(&pdc->eboText, pbrDefaultBrush, pdc); 00117 00118 /* Update the eboText's solid color */ 00119 EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboText, pdcattr->crForegroundClr); 00120 00121 /* Clear flag */ 00122 pdcattr->ulDirty_ &= ~DIRTY_TEXT; 00123 } 00124 00125 VOID 00126 FASTCALL 00127 DC_vUpdateBackgroundBrush(PDC pdc) 00128 { 00129 PDC_ATTR pdcattr = pdc->pdcattr; 00130 00131 if(pdcattr->ulDirty_ & DIRTY_BACKGROUND) 00132 EBRUSHOBJ_vUpdate(&pdc->eboBackground, pbrDefaultBrush, pdc); 00133 00134 /* Update the eboBackground's solid color */ 00135 EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboBackground, pdcattr->crBackgroundClr); 00136 00137 /* Clear flag */ 00138 pdcattr->ulDirty_ &= ~DIRTY_BACKGROUND; 00139 } 00140 00141 VOID 00142 NTAPI 00143 DC_vSetBrushOrigin(PDC pdc, LONG x, LONG y) 00144 { 00145 /* Set the brush origin */ 00146 pdc->dclevel.ptlBrushOrigin.x = x; 00147 pdc->dclevel.ptlBrushOrigin.y = y; 00148 00149 /* Set the fill origin */ 00150 pdc->ptlFillOrigin.x = x + pdc->ptlDCOrig.x; 00151 pdc->ptlFillOrigin.y = y + pdc->ptlDCOrig.y; 00152 } 00153 00162 BOOL 00163 APIENTRY 00164 NtGdiSetBrushOrg( 00165 _In_ HDC hdc, 00166 _In_ INT x, 00167 _In_ INT y, 00168 _Out_opt_ LPPOINT pptOut) 00169 { 00170 PDC pdc; 00171 00172 /* Lock the DC */ 00173 pdc = DC_LockDc(hdc); 00174 if (pdc == NULL) 00175 { 00176 EngSetLastError(ERROR_INVALID_HANDLE); 00177 return FALSE; 00178 } 00179 00180 /* Check if the old origin was requested */ 00181 if (pptOut != NULL) 00182 { 00183 /* Enter SEH for buffer transfer */ 00184 _SEH2_TRY 00185 { 00186 /* Probe and copy the old origin */ 00187 ProbeForWrite(pptOut, sizeof(POINT), 1); 00188 *pptOut = pdc->pdcattr->ptlBrushOrigin; 00189 } 00190 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00191 { 00192 DC_UnlockDc(pdc); 00193 _SEH2_YIELD(return FALSE); 00194 } 00195 _SEH2_END; 00196 } 00197 00198 /* Call the internal function */ 00199 DC_vSetBrushOrigin(pdc, x, y); 00200 00201 /* Unlock the DC and return success */ 00202 DC_UnlockDc(pdc); 00203 return TRUE; 00204 } 00205 00206 HPALETTE 00207 NTAPI 00208 GdiSelectPalette( 00209 HDC hDC, 00210 HPALETTE hpal, 00211 BOOL ForceBackground) 00212 { 00213 PDC pdc; 00214 HPALETTE oldPal = NULL; 00215 PPALETTE ppal; 00216 00217 // FIXME: Mark the palette as a [fore\back]ground pal 00218 pdc = DC_LockDc(hDC); 00219 if (!pdc) 00220 { 00221 return NULL; 00222 } 00223 00224 /* Check if this is a valid palette handle */ 00225 ppal = PALETTE_ShareLockPalette(hpal); 00226 if (!ppal) 00227 { 00228 DC_UnlockDc(pdc); 00229 return NULL; 00230 } 00231 00232 /* Is this a valid palette for this depth? */ 00233 if ((BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) <= 8 00234 && (ppal->flFlags & PAL_INDEXED)) || 00235 (BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) > 8)) 00236 { 00237 /* Get old palette, set new one */ 00238 oldPal = pdc->dclevel.hpal; 00239 pdc->dclevel.hpal = hpal; 00240 DC_vSelectPalette(pdc, ppal); 00241 00242 /* Mark the brushes invalid */ 00243 pdc->pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE | 00244 DIRTY_BACKGROUND | DIRTY_TEXT; 00245 } 00246 00247 if(pdc->dctype == DCTYPE_MEMORY) 00248 { 00249 // This didn't work anyway 00250 //IntGdiRealizePalette(hDC); 00251 } 00252 00253 PALETTE_ShareUnlockPalette(ppal); 00254 DC_UnlockDc(pdc); 00255 00256 return oldPal; 00257 } 00258 00259 /* 00260 * @implemented 00261 */ 00262 HBRUSH 00263 APIENTRY 00264 NtGdiSelectBrush( 00265 IN HDC hDC, 00266 IN HBRUSH hBrush) 00267 { 00268 PDC pDC; 00269 HBRUSH hOrgBrush; 00270 00271 if (hDC == NULL || hBrush == NULL) return NULL; 00272 00273 pDC = DC_LockDc(hDC); 00274 if (!pDC) 00275 { 00276 return NULL; 00277 } 00278 00279 /* Simply return the user mode value, without checking */ 00280 hOrgBrush = pDC->pdcattr->hbrush; 00281 pDC->pdcattr->hbrush = hBrush; 00282 DC_vUpdateFillBrush(pDC); 00283 00284 DC_UnlockDc(pDC); 00285 00286 return hOrgBrush; 00287 } 00288 00289 /* 00290 * @implemented 00291 */ 00292 HPEN 00293 APIENTRY 00294 NtGdiSelectPen( 00295 IN HDC hDC, 00296 IN HPEN hPen) 00297 { 00298 PDC pDC; 00299 HPEN hOrgPen; 00300 00301 if (hDC == NULL || hPen == NULL) return NULL; 00302 00303 pDC = DC_LockDc(hDC); 00304 if (!pDC) 00305 { 00306 return NULL; 00307 } 00308 00309 /* Simply return the user mode value, without checking */ 00310 hOrgPen = pDC->pdcattr->hpen; 00311 pDC->pdcattr->hpen = hPen; 00312 DC_vUpdateLineBrush(pDC); 00313 00314 DC_UnlockDc(pDC); 00315 00316 return hOrgPen; 00317 } 00318 00319 /* 00320 * @implemented 00321 */ 00322 HBITMAP 00323 APIENTRY 00324 NtGdiSelectBitmap( 00325 IN HDC hdc, 00326 IN HBITMAP hbmp) 00327 { 00328 PDC pdc; 00329 HBITMAP hbmpOld; 00330 PSURFACE psurfNew, psurfOld; 00331 HRGN hVisRgn; 00332 HDC hdcOld; 00333 ULONG cBitsPixel; 00334 ASSERT_NOGDILOCKS(); 00335 00336 /* Verify parameters */ 00337 if (hdc == NULL || hbmp == NULL) return NULL; 00338 00339 /* First lock the DC */ 00340 pdc = DC_LockDc(hdc); 00341 if (!pdc) 00342 { 00343 return NULL; 00344 } 00345 00346 /* Must be a memory dc to select a bitmap */ 00347 if (pdc->dctype != DC_TYPE_MEMORY) 00348 { 00349 DC_UnlockDc(pdc); 00350 return NULL; 00351 } 00352 00353 /* Save the old bitmap */ 00354 psurfOld = pdc->dclevel.pSurface; 00355 00356 /* Check if there is a bitmap selected */ 00357 if (psurfOld) 00358 { 00359 /* Get the old bitmap's handle */ 00360 hbmpOld = psurfOld->BaseObject.hHmgr; 00361 } 00362 else 00363 { 00364 /* Use the default bitmap */ 00365 hbmpOld = StockObjects[DEFAULT_BITMAP]; 00366 } 00367 00368 /* Check if the new bitmap is already selected */ 00369 if (hbmp == hbmpOld) 00370 { 00371 /* Unlock the DC and return the old bitmap */ 00372 DC_UnlockDc(pdc); 00373 return hbmpOld; 00374 } 00375 00376 /* Check if the default bitmap was passed */ 00377 if (hbmp == StockObjects[DEFAULT_BITMAP]) 00378 { 00379 psurfNew = NULL; 00380 00381 /* Default bitmap is 1x1 pixel */ 00382 pdc->dclevel.sizl.cx = 1; 00383 pdc->dclevel.sizl.cy = 1; 00384 00385 // HACK 00386 psurfNew = SURFACE_ShareLockSurface(hbmp); 00387 } 00388 else 00389 { 00390 /* Reference the new bitmap and check if it's valid */ 00391 psurfNew = SURFACE_ShareLockSurface(hbmp); 00392 if (!psurfNew) 00393 { 00394 DC_UnlockDc(pdc); 00395 return NULL; 00396 } 00397 00398 /* Check if the bitmap is compatile with the dc */ 00399 cBitsPixel = gajBitsPerFormat[psurfNew->SurfObj.iBitmapFormat]; 00400 if ((cBitsPixel != 1) && 00401 (cBitsPixel != pdc->ppdev->gdiinfo.cBitsPixel) && 00402 (psurfNew->hSecure == NULL)) 00403 { 00404 /* Dereference the bitmap, unlock the DC and fail. */ 00405 SURFACE_ShareUnlockSurface(psurfNew); 00406 DC_UnlockDc(pdc); 00407 return NULL; 00408 } 00409 00410 /* Set the bitmap's hdc and check if it was set before */ 00411 hdcOld = InterlockedCompareExchangePointer((PVOID*)&psurfNew->hdc, hdc, 0); 00412 if (hdcOld != NULL) 00413 { 00414 /* The bitmap is already selected into a different DC */ 00415 ASSERT(hdcOld != hdc); 00416 00417 /* Dereference the bitmap, unlock the DC and fail. */ 00418 SURFACE_ShareUnlockSurface(psurfNew); 00419 DC_UnlockDc(pdc); 00420 return NULL; 00421 } 00422 00423 /* Copy the bitmap size */ 00424 pdc->dclevel.sizl = psurfNew->SurfObj.sizlBitmap; 00425 00426 /* Check if the bitmap is a dibsection */ 00427 if (psurfNew->hSecure) 00428 { 00429 /* Set DIBSECTION attribute */ 00430 pdc->pdcattr->ulDirty_ |= DC_DIBSECTION; 00431 } 00432 else 00433 { 00434 /* Remove DIBSECTION attribute */ 00435 pdc->pdcattr->ulDirty_ &= ~DC_DIBSECTION; 00436 } 00437 } 00438 00439 /* Select the new bitmap */ 00440 pdc->dclevel.pSurface = psurfNew; 00441 00442 /* Check if there was a bitmap selected before */ 00443 if (psurfOld) 00444 { 00445 /* Reset hdc of the old bitmap, it isn't selected anymore */ 00446 psurfOld->hdc = NULL; 00447 00448 /* Dereference the old bitmap */ 00449 SURFACE_ShareUnlockSurface(psurfOld); 00450 } 00451 00452 /* Mark the dc brushes invalid */ 00453 pdc->pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE; 00454 00455 /* FIXME: Improve by using a region without a handle and selecting it */ 00456 hVisRgn = IntSysCreateRectRgn( 0, 00457 0, 00458 pdc->dclevel.sizl.cx, 00459 pdc->dclevel.sizl.cy); 00460 00461 if (hVisRgn) 00462 { 00463 GdiSelectVisRgn(hdc, hVisRgn); 00464 GreDeleteObject(hVisRgn); 00465 } 00466 00467 /* Unlock the DC */ 00468 DC_UnlockDc(pdc); 00469 00470 /* Return the old bitmap handle */ 00471 return hbmpOld; 00472 } 00473 00474 00475 BOOL 00476 APIENTRY 00477 NtGdiSelectClipPath( 00478 HDC hDC, 00479 int Mode) 00480 { 00481 HRGN hrgnPath; 00482 PPATH pPath; 00483 BOOL success = FALSE; 00484 PDC_ATTR pdcattr; 00485 PDC pdc; 00486 00487 pdc = DC_LockDc(hDC); 00488 if (!pdc) 00489 { 00490 EngSetLastError(ERROR_INVALID_PARAMETER); 00491 return FALSE; 00492 } 00493 pdcattr = pdc->pdcattr; 00494 00495 pPath = PATH_LockPath(pdc->dclevel.hPath); 00496 if (!pPath) 00497 { 00498 DC_UnlockDc(pdc); 00499 return FALSE; 00500 } 00501 00502 /* Check that path is closed */ 00503 if (pPath->state != PATH_Closed) 00504 { 00505 EngSetLastError(ERROR_CAN_NOT_COMPLETE); 00506 DC_UnlockDc(pdc); 00507 return FALSE; 00508 } 00509 00510 /* Construct a region from the path */ 00511 else if (PATH_PathToRegion(pPath, pdcattr->jFillMode, &hrgnPath)) 00512 { 00513 success = GdiExtSelectClipRgn(pdc, hrgnPath, Mode) != ERROR; 00514 GreDeleteObject( hrgnPath ); 00515 00516 /* Empty the path */ 00517 if (success) 00518 PATH_EmptyPath(pPath); 00519 00520 /* FIXME: Should this function delete the path even if it failed? */ 00521 } 00522 00523 PATH_UnlockPath(pPath); 00524 DC_UnlockDc(pdc); 00525 00526 return success; 00527 } 00528 00529 HANDLE 00530 APIENTRY 00531 NtGdiGetDCObject(HDC hDC, INT ObjectType) 00532 { 00533 HGDIOBJ SelObject; 00534 DC *pdc; 00535 PDC_ATTR pdcattr; 00536 00537 /* From Wine: GetCurrentObject does not SetLastError() on a null object */ 00538 if(!hDC) return NULL; 00539 00540 if(!(pdc = DC_LockDc(hDC))) 00541 { 00542 return NULL; 00543 } 00544 pdcattr = pdc->pdcattr; 00545 00546 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) 00547 DC_vUpdateFillBrush(pdc); 00548 00549 if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY)) 00550 DC_vUpdateLineBrush(pdc); 00551 00552 switch(ObjectType) 00553 { 00554 case GDI_OBJECT_TYPE_EXTPEN: 00555 case GDI_OBJECT_TYPE_PEN: 00556 SelObject = pdcattr->hpen; 00557 break; 00558 00559 case GDI_OBJECT_TYPE_BRUSH: 00560 SelObject = pdcattr->hbrush; 00561 break; 00562 00563 case GDI_OBJECT_TYPE_PALETTE: 00564 SelObject = pdc->dclevel.hpal; 00565 break; 00566 00567 case GDI_OBJECT_TYPE_FONT: 00568 SelObject = pdcattr->hlfntNew; 00569 break; 00570 00571 case GDI_OBJECT_TYPE_BITMAP: 00572 { 00573 SURFACE *psurf = pdc->dclevel.pSurface; 00574 SelObject = psurf ? psurf->BaseObject.hHmgr : NULL; 00575 break; 00576 } 00577 00578 case GDI_OBJECT_TYPE_COLORSPACE: 00579 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n"); 00580 // SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ? 00581 SelObject = NULL; 00582 break; 00583 00584 default: 00585 SelObject = NULL; 00586 EngSetLastError(ERROR_INVALID_PARAMETER); 00587 break; 00588 } 00589 00590 DC_UnlockDc(pdc); 00591 return SelObject; 00592 } 00593 00594 /* See WINE, MSDN, OSR and Feng Yuan - Windows Graphics Programming Win32 GDI and DirectDraw 00595 * 00596 * 1st: http://www.codeproject.com/gdi/cliprgnguide.asp is wrong! 00597 * 00598 * The intersection of the clip with the meta region is not Rao it's API! 00599 * Go back and read 7.2 Clipping pages 418-19: 00600 * Rao = API & Vis: 00601 * 1) The Rao region is the intersection of the API region and the system region, 00602 * named after the Microsoft engineer who initially proposed it. 00603 * 2) The Rao region can be calculated from the API region and the system region. 00604 * 00605 * API: 00606 * API region is the intersection of the meta region and the clipping region, 00607 * clearly named after the fact that it is controlled by GDI API calls. 00608 */ 00609 INT 00610 APIENTRY 00611 NtGdiGetRandomRgn( 00612 HDC hdc, 00613 HRGN hrgnDest, 00614 INT iCode) 00615 { 00616 INT ret = 0; 00617 PDC pdc; 00618 HRGN hrgnSrc = NULL; 00619 POINTL ptlOrg; 00620 00621 pdc = DC_LockDc(hdc); 00622 if (!pdc) 00623 { 00624 EngSetLastError(ERROR_INVALID_PARAMETER); 00625 return -1; 00626 } 00627 00628 switch (iCode) 00629 { 00630 case CLIPRGN: 00631 hrgnSrc = pdc->rosdc.hClipRgn; 00632 // if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr; 00633 break; 00634 case METARGN: 00635 if (pdc->dclevel.prgnMeta) 00636 hrgnSrc = pdc->dclevel.prgnMeta->BaseObject.hHmgr; 00637 break; 00638 case APIRGN: 00639 if (pdc->prgnAPI) hrgnSrc = pdc->prgnAPI->BaseObject.hHmgr; 00640 // else if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr; 00641 else if (pdc->rosdc.hClipRgn) hrgnSrc = pdc->rosdc.hClipRgn; 00642 else if (pdc->dclevel.prgnMeta) hrgnSrc = pdc->dclevel.prgnMeta->BaseObject.hHmgr; 00643 break; 00644 case SYSRGN: 00645 if (pdc->prgnVis) 00646 { 00647 PREGION prgnDest = REGION_LockRgn(hrgnDest); 00648 ret = IntGdiCombineRgn(prgnDest, pdc->prgnVis, 0, RGN_COPY) == ERROR ? -1 : 1; 00649 REGION_UnlockRgn(prgnDest); 00650 } 00651 break; 00652 default: 00653 hrgnSrc = NULL; 00654 } 00655 00656 if (hrgnSrc) 00657 { 00658 ret = NtGdiCombineRgn(hrgnDest, hrgnSrc, 0, RGN_COPY) == ERROR ? -1 : 1; 00659 } 00660 00661 if (iCode == SYSRGN) 00662 { 00663 ptlOrg = pdc->ptlDCOrig; 00664 NtGdiOffsetRgn(hrgnDest, ptlOrg.x, ptlOrg.y ); 00665 } 00666 00667 DC_UnlockDc(pdc); 00668 00669 return ret; 00670 } 00671 00672 ULONG 00673 APIENTRY 00674 NtGdiEnumObjects( 00675 IN HDC hdc, 00676 IN INT iObjectType, 00677 IN ULONG cjBuf, 00678 OUT OPTIONAL PVOID pvBuf) 00679 { 00680 UNIMPLEMENTED; 00681 return 0; 00682 } 00683 00684 /* EOF */ Generated on Fri May 25 2012 04:36:34 for ReactOS by
1.7.6.1
|