BOOL NTAPI DC_Cleanup(PVOID ObjectBody) { PDC pdc = (PDC)ObjectBody; /* Free DC_ATTR */ DC_vFreeDcAttr(pdc); /* Delete saved DCs */ DC_vRestoreDC(pdc, 1); /* Deselect dc objects */ DC_vSelectSurface(pdc, NULL); DC_vSelectFillBrush(pdc, NULL); DC_vSelectLineBrush(pdc, NULL); DC_vSelectPalette(pdc, NULL); /* Cleanup the dc brushes */ EBRUSHOBJ_vCleanup(&pdc->eboFill); EBRUSHOBJ_vCleanup(&pdc->eboLine); EBRUSHOBJ_vCleanup(&pdc->eboText); EBRUSHOBJ_vCleanup(&pdc->eboBackground); /* Release font */ LFONT_ShareUnlockFont(pdc->dclevel.plfnt); /* Free regions */ if (pdc->rosdc.hClipRgn && GreIsHandleValid(pdc->rosdc.hClipRgn)) GreDeleteObject(pdc->rosdc.hClipRgn); if (pdc->prgnVis) { REGION_Delete(pdc->prgnVis); } if (pdc->rosdc.hGCClipRgn && GreIsHandleValid(pdc->rosdc.hGCClipRgn)) { GreDeleteObject(pdc->rosdc.hGCClipRgn); } if (NULL != pdc->rosdc.CombinedClip) IntEngDeleteClipRegion(pdc->rosdc.CombinedClip); PATH_Delete(pdc->dclevel.hPath); if(pdc->dclevel.pSurface) SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface); PDEVOBJ_vRelease(pdc->ppdev) ; return TRUE; }
VOID NTAPI DC_vCleanup(PVOID ObjectBody) { PDC pdc = (PDC)ObjectBody; /* Free DC_ATTR */ DC_vFreeDcAttr(pdc); /* Delete saved DCs */ DC_vRestoreDC(pdc, 1); /* Deselect dc objects */ DC_vSelectSurface(pdc, NULL); DC_vSelectFillBrush(pdc, NULL); DC_vSelectLineBrush(pdc, NULL); DC_vSelectPalette(pdc, NULL); /* Cleanup the dc brushes */ EBRUSHOBJ_vCleanup(&pdc->eboFill); EBRUSHOBJ_vCleanup(&pdc->eboLine); EBRUSHOBJ_vCleanup(&pdc->eboText); EBRUSHOBJ_vCleanup(&pdc->eboBackground); /* Release font */ LFONT_ShareUnlockFont(pdc->dclevel.plfnt); /* Free regions */ if (pdc->dclevel.prgnClip) REGION_Delete(pdc->dclevel.prgnClip); if (pdc->dclevel.prgnMeta) REGION_Delete(pdc->dclevel.prgnMeta); if (pdc->prgnVis) REGION_Delete(pdc->prgnVis); if (pdc->prgnRao) REGION_Delete(pdc->prgnRao); if (pdc->prgnAPI) REGION_Delete(pdc->prgnAPI); /* Free CLIPOBJ resources */ IntEngFreeClipResources(&pdc->co); PATH_Delete(pdc->dclevel.hPath); if(pdc->dclevel.pSurface) SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface); PDEVOBJ_vRelease(pdc->ppdev) ; }
BOOL FASTCALL IntGdiPolyPatBlt( HDC hDC, DWORD dwRop, PPATRECT pRects, INT cRects, ULONG Reserved) { INT i; PBRUSH pbrush; PDC pdc; EBRUSHOBJ eboFill; pdc = DC_LockDc(hDC); if (!pdc) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } if (pdc->dctype == DC_TYPE_INFO) { DC_UnlockDc(pdc); /* Yes, Windows really returns TRUE in this case */ return TRUE; } for (i = 0; i < cRects; i++) { pbrush = BRUSH_ShareLockBrush(pRects->hBrush); /* Check if we could lock the brush */ if (pbrush != NULL) { /* Initialize a brush object */ EBRUSHOBJ_vInitFromDC(&eboFill, pbrush, pdc); IntPatBlt( pdc, pRects->r.left, pRects->r.top, pRects->r.right, pRects->r.bottom, dwRop, &eboFill); /* Cleanup the brush object and unlock the brush */ EBRUSHOBJ_vCleanup(&eboFill); BRUSH_ShareUnlockBrush(pbrush); } pRects++; } DC_UnlockDc(pdc); return TRUE; }
VOID NTAPI EBRUSHOBJ_vUpdateFromDC( EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc) { /* Cleanup the brush */ EBRUSHOBJ_vCleanup(pebo); /* Reinitialize */ EBRUSHOBJ_vInitFromDC(pebo, pbrush, pdc); }
BOOL FASTCALL IntPatBlt( PDC pdc, INT XLeft, INT YLeft, INT Width, INT Height, DWORD dwRop, PBRUSH pbrush) { RECTL DestRect; SURFACE *psurf; EBRUSHOBJ eboFill ; POINTL BrushOrigin; BOOL ret; ASSERT(pbrush); FIXUP_ROP(dwRop); if (pbrush->flAttrs & GDIBRUSH_IS_NULL) { return TRUE; } if (Width > 0) { DestRect.left = XLeft; DestRect.right = XLeft + Width; } else { DestRect.left = XLeft + Width + 1; DestRect.right = XLeft + 1; } if (Height > 0) { DestRect.top = YLeft; DestRect.bottom = YLeft + Height; } else { DestRect.top = YLeft + Height + 1; DestRect.bottom = YLeft + 1; } IntLPtoDP(pdc, (LPPOINT)&DestRect, 2); DestRect.left += pdc->ptlDCOrig.x; DestRect.top += pdc->ptlDCOrig.y; DestRect.right += pdc->ptlDCOrig.x; DestRect.bottom += pdc->ptlDCOrig.y; #ifdef _USE_DIBLIB_ BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x + XLeft; BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y + YLeft; #else BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x; BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y; #endif DC_vPrepareDCsForBlit(pdc, DestRect, NULL, DestRect); psurf = pdc->dclevel.pSurface; if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(pdc); EBRUSHOBJ_vInit(&eboFill, pbrush, pdc); ret = IntEngBitBlt( &psurf->SurfObj, NULL, NULL, pdc->rosdc.CombinedClip, NULL, &DestRect, NULL, NULL, &eboFill.BrushObject, &BrushOrigin, ROP_TO_ROP4(dwRop)); DC_vFinishBlit(pdc, NULL); EBRUSHOBJ_vCleanup(&eboFill); return ret; }
/* Mostly inspired from wine code. * We use low level functions because: * - at this point, the icon bitmap could have a different bit depth than the DC, * making it thus impossible to use NtCreateCompatibleDC and selecting the bitmap. * This happens after a mode setting change. * - it avoids massive GDI objects locking when only the destination surface needs it. * - It makes (small) performance gains. */ BOOL UserDrawIconEx( HDC hDc, INT xLeft, INT yTop, PCURICON_OBJECT pIcon, INT cxWidth, INT cyHeight, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags) { PSURFACE psurfDest, psurfMask, psurfColor; //, psurfOffScreen = NULL; PDC pdc = NULL; BOOL Ret = FALSE; HBITMAP hbmMask, hbmColor, hbmAlpha; BOOL bOffScreen; RECTL rcDest, rcSrc; CLIPOBJ* pdcClipObj = NULL; EXLATEOBJ exlo; /* Stupid case */ if((diFlags & DI_NORMAL) == 0) { ERR("DrawIconEx called without mask or color bitmap to draw.\n"); return FALSE; } if (pIcon->CURSORF_flags & CURSORF_ACON) { ACON* pAcon = (ACON*)pIcon; if(istepIfAniCur >= pAcon->cicur) { ERR("NtUserDrawIconEx: istepIfAniCur too big!\n"); return FALSE; } pIcon = pAcon->aspcur[pAcon->aicur[istepIfAniCur]]; } hbmMask = pIcon->hbmMask; hbmColor = pIcon->hbmColor; hbmAlpha = pIcon->hbmAlpha; /* * Get our objects. * Shared locks are enough, we are only reading those bitmaps */ psurfMask = SURFACE_ShareLockSurface(hbmMask); if(psurfMask == NULL) { ERR("Unable to lock the mask surface.\n"); return FALSE; } /* Color bitmap is not mandatory */ if(hbmColor == NULL) { /* But then the mask bitmap must have the information in it's bottom half */ ASSERT(psurfMask->SurfObj.sizlBitmap.cy == 2*pIcon->cy); psurfColor = NULL; } else if ((psurfColor = SURFACE_ShareLockSurface(hbmColor)) == NULL) { ERR("Unable to lock the color bitmap.\n"); SURFACE_ShareUnlockSurface(psurfMask); return FALSE; } pdc = DC_LockDc(hDc); if(!pdc) { ERR("Could not lock the destination DC.\n"); SURFACE_ShareUnlockSurface(psurfMask); if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); return FALSE; } /* Calculate destination rectangle */ RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); /* Prepare the underlying surface */ DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest); /* We now have our destination surface and rectangle */ psurfDest = pdc->dclevel.pSurface; if(psurfDest == NULL) { /* Empty DC */ DC_vFinishBlit(pdc, NULL); DC_UnlockDc(pdc); SURFACE_ShareUnlockSurface(psurfMask); if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); return FALSE; } /* Set source rect */ RECTL_vSetRect(&rcSrc, 0, 0, pIcon->cx, pIcon->cy); /* Fix width parameter, if needed */ if (!cxWidth) { if(diFlags & DI_DEFAULTSIZE) cxWidth = is_icon(pIcon) ? UserGetSystemMetrics(SM_CXICON) : UserGetSystemMetrics(SM_CXCURSOR); else cxWidth = pIcon->cx; } /* Fix height parameter, if needed */ if (!cyHeight) { if(diFlags & DI_DEFAULTSIZE) cyHeight = is_icon(pIcon) ? UserGetSystemMetrics(SM_CYICON) : UserGetSystemMetrics(SM_CYCURSOR); else cyHeight = pIcon->cy; } /* Should we render off-screen? */ bOffScreen = hbrFlickerFreeDraw && (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH); if (bOffScreen) { /* Yes: Allocate and paint the offscreen surface */ EBRUSHOBJ eboFill; PBRUSH pbrush = BRUSH_ShareLockBrush(hbrFlickerFreeDraw); TRACE("Performing off-screen rendering.\n"); if(!pbrush) { ERR("Failed to get brush object.\n"); goto Cleanup; } #if 0 //We lock the hdc surface during the whole function it makes no sense to use an offscreen surface for "flicker free" drawing psurfOffScreen = SURFACE_AllocSurface(STYPE_BITMAP, cxWidth, cyHeight, psurfDest->SurfObj.iBitmapFormat, 0, 0, NULL); if(!psurfOffScreen) { ERR("Failed to allocate the off-screen surface.\n"); BRUSH_ShareUnlockBrush(pbrush); goto Cleanup; } /* Paint the brush */ EBRUSHOBJ_vInit(&eboFill, pbrush, psurfOffScreen, 0x00FFFFFF, 0, NULL); RECTL_vSetRect(&rcDest, 0, 0, cxWidth, cyHeight); Ret = IntEngBitBlt(&psurfOffScreen->SurfObj, NULL, NULL, NULL, NULL, &rcDest, NULL, NULL, &eboFill.BrushObject, &pbrush->ptOrigin, ROP4_PATCOPY); /* Clean up everything */ EBRUSHOBJ_vCleanup(&eboFill); BRUSH_ShareUnlockBrush(pbrush); if(!Ret) { ERR("Failed to paint the off-screen surface.\n"); goto Cleanup; } /* We now have our destination surface */ psurfDest = psurfOffScreen; #else pdcClipObj = pdc->rosdc.CombinedClip; /* Paint the brush */ EBRUSHOBJ_vInit(&eboFill, pbrush, psurfDest, 0x00FFFFFF, 0, NULL); Ret = IntEngBitBlt(&psurfDest->SurfObj, NULL, NULL, pdcClipObj, NULL, &rcDest, NULL, NULL, &eboFill.BrushObject, &pbrush->ptOrigin, ROP4_PATCOPY); /* Clean up everything */ EBRUSHOBJ_vCleanup(&eboFill); BRUSH_ShareUnlockBrush(pbrush); if(!Ret) { ERR("Failed to paint the off-screen surface.\n"); goto Cleanup; } #endif } else { /* We directly draw to the DC */ TRACE("Performing on screen rendering.\n"); pdcClipObj = pdc->rosdc.CombinedClip; // psurfOffScreen = NULL; } /* Now do the rendering */ if(hbmAlpha && ((diFlags & DI_NORMAL) == DI_NORMAL)) { BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } }; PSURFACE psurf = NULL; psurf = SURFACE_ShareLockSurface(hbmAlpha); if(!psurf) { ERR("SURFACE_LockSurface failed!\n"); goto NoAlpha; } /* Initialize color translation object */ EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xFFFFFFFF, 0xFFFFFFFF, 0); /* Now do it */ Ret = IntEngAlphaBlend(&psurfDest->SurfObj, &psurf->SurfObj, pdcClipObj, &exlo.xlo, &rcDest, &rcSrc, &blendobj); EXLATEOBJ_vCleanup(&exlo); SURFACE_ShareUnlockSurface(psurf); if(Ret) goto done; ERR("NtGdiAlphaBlend failed!\n"); } NoAlpha: if (diFlags & DI_MASK) { DWORD rop4 = (diFlags & DI_IMAGE) ? ROP4_SRCAND : ROP4_SRCCOPY; EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0); Ret = IntEngStretchBlt(&psurfDest->SurfObj, &psurfMask->SurfObj, NULL, pdcClipObj, &exlo.xlo, NULL, &rcDest, &rcSrc, NULL, NULL, NULL, rop4); EXLATEOBJ_vCleanup(&exlo); if(!Ret) { ERR("Failed to mask the bitmap data.\n"); goto Cleanup; } } if(diFlags & DI_IMAGE) { if (psurfColor) { DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY ; EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0); Ret = IntEngStretchBlt(&psurfDest->SurfObj, &psurfColor->SurfObj, NULL, pdcClipObj, &exlo.xlo, NULL, &rcDest, &rcSrc, NULL, NULL, NULL, rop4); EXLATEOBJ_vCleanup(&exlo); if(!Ret) { ERR("Failed to render the icon bitmap.\n"); goto Cleanup; } } else { /* Mask bitmap holds the information in its bottom half */ DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY; RECTL_vOffsetRect(&rcSrc, 0, pIcon->cy); EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0); Ret = IntEngStretchBlt(&psurfDest->SurfObj, &psurfMask->SurfObj, NULL, pdcClipObj, &exlo.xlo, NULL, &rcDest, &rcSrc, NULL, NULL, NULL, rop4); EXLATEOBJ_vCleanup(&exlo); if(!Ret) { ERR("Failed to render the icon bitmap.\n"); goto Cleanup; } } } done: #if 0 /* We're done. Was it a double buffered draw ? */ if(bOffScreen) { /* Yes. Draw it back to our DC */ POINTL ptSrc = {0, 0}; /* Calculate destination rectangle */ RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); /* Get the clip object */ pdcClipObj = pdc->rosdc.CombinedClip; /* We now have our destination surface and rectangle */ psurfDest = pdc->dclevel.pSurface; /* Color translation */ EXLATEOBJ_vInitialize(&exlo, psurfOffScreen->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0); /* Blt it! */ Ret = IntEngBitBlt(&psurfDest->SurfObj, &psurfOffScreen->SurfObj, NULL, pdcClipObj, &exlo.xlo, &rcDest, &ptSrc, NULL, NULL, NULL, ROP4_SRCCOPY); EXLATEOBJ_vCleanup(&exlo); } #endif Cleanup: if(pdc) { DC_vFinishBlit(pdc, NULL); DC_UnlockDc(pdc); } #if 0 /* Delete off screen rendering surface */ if(psurfOffScreen) GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject); #endif /* Unlock other surfaces */ SURFACE_ShareUnlockSurface(psurfMask); if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); return Ret; }