VOID FASTCALL EBRUSHOBJ_vSetSolidRGBColor(EBRUSHOBJ *pebo, COLORREF crColor) { ULONG iSolidColor; EXLATEOBJ exlo; /* Never use with non-solid brushes */ ASSERT(pebo->flattrs & BR_IS_SOLID); /* Set the RGB color */ crColor &= 0xFFFFFF; pebo->crRealize = crColor; pebo->ulRGBColor = crColor; /* Initialize an XLATEOBJ RGB -> surface */ EXLATEOBJ_vInitialize(&exlo, &gpalRGB, pebo->ppalSurf, pebo->crCurrentBack, 0, 0); /* Translate the brush color to the target format */ iSolidColor = XLATEOBJ_iXlate(&exlo.xlo, crColor); pebo->BrushObject.iSolidColor = iSolidColor; /* Clean up the XLATEOBJ */ EXLATEOBJ_vCleanup(&exlo); }
COLORREF APIENTRY NtGdiGetNearestColor( _In_ HDC hDC, _In_ COLORREF Color) { COLORREF nearest = CLR_INVALID; PDC dc; EXLATEOBJ exlo; PPALETTE ppal; dc = DC_LockDc(hDC); if(dc == NULL) { EngSetLastError(ERROR_INVALID_HANDLE); return CLR_INVALID; } if(dc->dclevel.pSurface == NULL) ppal = gppalMono; else ppal = dc->dclevel.pSurface->ppal; /* Translate the color to the DC format */ Color = TranslateCOLORREF(dc, Color); /* XLATE it back to RGB color space */ EXLATEOBJ_vInitialize(&exlo, ppal, &gpalRGB, 0, RGB(0xff, 0xff, 0xff), RGB(0, 0, 0)); nearest = XLATEOBJ_iXlate(&exlo.xlo, Color); EXLATEOBJ_vCleanup(&exlo); /* We're done */ DC_UnlockDc(dc); return nearest; }
ULONG NTAPI GreSetPointerShape( _In_ HDC hdc, _In_opt_ HBITMAP hbmMask, _In_opt_ HBITMAP hbmColor, _In_ LONG xHot, _In_ LONG yHot, _In_ LONG x, _In_ LONG y, _In_ FLONG fl) { PDC pdc; PSURFACE psurf, psurfMask, psurfColor; EXLATEOBJ exlo; ULONG ulResult = 0; pdc = DC_LockDc(hdc); if (!pdc) { DPRINT1("Failed to lock the DC.\n"); return 0; } ASSERT(pdc->dctype == DCTYPE_DIRECT); EngAcquireSemaphore(pdc->ppdev->hsemDevLock); /* We're not sure DC surface is the good one */ psurf = pdc->ppdev->pSurface; if (!psurf) { DPRINT1("DC has no surface.\n"); EngReleaseSemaphore(pdc->ppdev->hsemDevLock); DC_UnlockDc(pdc); return 0; } /* Lock the mask bitmap */ if (hbmMask) { psurfMask = SURFACE_ShareLockSurface(hbmMask); } else { //ASSERT(fl & SPS_ALPHA); psurfMask = NULL; } /* Check for color bitmap */ if (hbmColor) { /* We have one, lock it */ psurfColor = SURFACE_ShareLockSurface(hbmColor); if (psurfColor) { /* Create an XLATEOBJ, no mono support */ EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurf->ppal, 0, 0, 0); } } else psurfColor = NULL; /* We must have a valid surface in case of alpha bitmap */ ASSERT(((fl & SPS_ALPHA) && psurfColor) || !(fl & SPS_ALPHA)); /* Call the driver or eng function */ ulResult = IntEngSetPointerShape(&psurf->SurfObj, psurfMask ? &psurfMask->SurfObj : NULL, psurfColor ? &psurfColor->SurfObj : NULL, psurfColor ? &exlo.xlo : NULL, xHot, yHot, x, y, &pdc->ppdev->Pointer.Exclude, fl | SPS_CHANGE); /* Cleanup */ if (psurfColor) { EXLATEOBJ_vCleanup(&exlo); SURFACE_ShareUnlockSurface(psurfColor); } if (psurfMask) SURFACE_ShareUnlockSurface(psurfMask); EngReleaseSemaphore(pdc->ppdev->hsemDevLock); /* Unlock the DC */ DC_UnlockDc(pdc); /* Return result */ return ulResult; }
/* * @implemented */ ULONG APIENTRY EngSetPointerShape( _In_ SURFOBJ *pso, _In_opt_ SURFOBJ *psoMask, _In_opt_ SURFOBJ *psoColor, _In_opt_ XLATEOBJ *pxlo, _In_ LONG xHot, _In_ LONG yHot, _In_ LONG x, _In_ LONG y, _In_ RECTL *prcl, _In_ FLONG fl) { PDEVOBJ *ppdev; GDIPOINTER *pgp; LONG lDelta = 0; HBITMAP hbmSave = NULL, hbmColor = NULL, hbmMask = NULL; PSURFACE psurfSave = NULL, psurfColor = NULL, psurfMask = NULL; RECTL rectl; SIZEL sizel = {0, 0}; ASSERT(pso); ppdev = GDIDEV(pso); pgp = &ppdev->Pointer; /* Handle the case where we have no XLATEOBJ */ if (pxlo == NULL) pxlo = &gexloTrivial.xlo; /* Do we have any bitmap at all? */ if (psoColor || psoMask) { /* Get the size of the new pointer */ if (psoColor) { sizel.cx = psoColor->sizlBitmap.cx; sizel.cy = psoColor->sizlBitmap.cy; } else// if (psoMask) { sizel.cx = psoMask->sizlBitmap.cx; sizel.cy = psoMask->sizlBitmap.cy / 2; } rectl.left = 0; rectl.top = 0; rectl.right = sizel.cx; rectl.bottom = sizel.cy; /* Calculate lDelta for our surfaces. */ lDelta = WIDTH_BYTES_ALIGN32(sizel.cx, BitsPerFormat(pso->iBitmapFormat)); /* Create a bitmap for saving the pixels under the cursor. */ hbmSave = EngCreateBitmap(sizel, lDelta, pso->iBitmapFormat, BMF_TOPDOWN | BMF_NOZEROINIT, NULL); psurfSave = SURFACE_ShareLockSurface(hbmSave); if (!psurfSave) goto failure; } if (psoColor) { if (fl & SPS_ALPHA) { /* Always store the alpha cursor in RGB. */ EXLATEOBJ exloSrcRGB; PEXLATEOBJ pexlo; pexlo = CONTAINING_RECORD(pxlo, EXLATEOBJ, xlo); EXLATEOBJ_vInitialize(&exloSrcRGB, pexlo->ppalSrc, &gpalRGB, 0, 0, 0); hbmColor = EngCreateBitmap(psoColor->sizlBitmap, WIDTH_BYTES_ALIGN32(sizel.cx, 32), BMF_32BPP, BMF_TOPDOWN | BMF_NOZEROINIT, NULL); psurfColor = SURFACE_ShareLockSurface(hbmColor); if (!psurfColor) goto failure; /* Now copy the given bitmap. */ rectl.bottom = psoColor->sizlBitmap.cy; IntEngCopyBits(&psurfColor->SurfObj, psoColor, NULL, &exloSrcRGB.xlo, &rectl, (POINTL*)&rectl); EXLATEOBJ_vCleanup(&exloSrcRGB); } else { /* Color bitmap must have the same format as the dest surface */ if (psoColor->iBitmapFormat != pso->iBitmapFormat) { DPRINT1("Screen surface and cursor color bitmap format don't match!.\n"); goto failure; } /* Create a bitmap to copy the color bitmap to */ hbmColor = EngCreateBitmap(psoColor->sizlBitmap, lDelta, pso->iBitmapFormat, BMF_TOPDOWN | BMF_NOZEROINIT, NULL); psurfColor = SURFACE_ShareLockSurface(hbmColor); if (!psurfColor) goto failure; /* Now copy the given bitmap. */ rectl.bottom = psoColor->sizlBitmap.cy; IntEngCopyBits(&psurfColor->SurfObj, psoColor, NULL, pxlo, &rectl, (POINTL*)&rectl); } } /* Create a mask surface */ if (psoMask) { EXLATEOBJ exlo; PPALETTE ppal; lDelta = WIDTH_BYTES_ALIGN32(sizel.cx, BitsPerFormat(pso->iBitmapFormat)); /* Create a bitmap for the mask */ hbmMask = EngCreateBitmap(psoMask->sizlBitmap, lDelta, pso->iBitmapFormat, BMF_TOPDOWN | BMF_NOZEROINIT, NULL); psurfMask = SURFACE_ShareLockSurface(hbmMask); if (!psurfMask) goto failure; /* Initialize an EXLATEOBJ */ ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault); EXLATEOBJ_vInitialize(&exlo, gppalMono, ppal, 0, RGB(0xff,0xff,0xff), RGB(0,0,0)); /* Copy the mask bitmap */ rectl.bottom = psoMask->sizlBitmap.cy; IntEngCopyBits(&psurfMask->SurfObj, psoMask, NULL, &exlo.xlo, &rectl, (POINTL*)&rectl); /* Cleanup */ EXLATEOBJ_vCleanup(&exlo); if (ppal) PALETTE_ShareUnlockPalette(ppal); } /* Hide mouse pointer */ IntHideMousePointer(ppdev, pso); /* Free old color bitmap */ if (pgp->psurfColor) { EngDeleteSurface(pgp->psurfColor->BaseObject.hHmgr); SURFACE_ShareUnlockSurface(pgp->psurfColor); pgp->psurfColor = NULL; } /* Free old mask bitmap */ if (pgp->psurfMask) { EngDeleteSurface(pgp->psurfMask->BaseObject.hHmgr); SURFACE_ShareUnlockSurface(pgp->psurfMask); pgp->psurfMask = NULL; } /* Free old save bitmap */ if (pgp->psurfSave) { EngDeleteSurface(pgp->psurfSave->BaseObject.hHmgr); SURFACE_ShareUnlockSurface(pgp->psurfSave); pgp->psurfSave = NULL; } /* See if we are being asked to hide the pointer. */ if (psoMask == NULL && psoColor == NULL) { /* We're done */ return SPS_ACCEPT_NOEXCLUDE; } /* Now set the new cursor */ pgp->psurfColor = psurfColor; pgp->psurfMask = psurfMask; pgp->psurfSave = psurfSave; pgp->HotSpot.x = xHot; pgp->HotSpot.y = yHot; pgp->Size = sizel; pgp->flags = fl; if (x != -1) { ppdev->ptlPointer.x = x; ppdev->ptlPointer.y = y; IntShowMousePointer(ppdev, pso); if (prcl != NULL) { prcl->left = x - pgp->HotSpot.x; prcl->top = y - pgp->HotSpot.x; prcl->right = prcl->left + pgp->Size.cx; prcl->bottom = prcl->top + pgp->Size.cy; } } else if (prcl != NULL) { prcl->left = prcl->top = prcl->right = prcl->bottom = -1; } return SPS_ACCEPT_NOEXCLUDE; failure: /* Cleanup surfaces */ if (hbmMask) EngDeleteSurface((HSURF)hbmMask); if (psurfMask) SURFACE_ShareUnlockSurface(psurfMask); if (hbmColor) EngDeleteSurface((HSURF)hbmColor); if (psurfColor) SURFACE_ShareUnlockSurface(psurfColor); if (hbmSave) EngDeleteSurface((HSURF)hbmSave); if (psurfSave) SURFACE_ShareUnlockSurface(psurfSave); return SPS_ERROR; }
VOID NTAPI IntShowMousePointer( _Inout_ PDEVOBJ *ppdev, _Inout_ SURFOBJ *psoDest) { GDIPOINTER *pgp; POINTL pt; RECTL rclSurf, rclPointer; ASSERT(ppdev); ASSERT(psoDest); pgp = &ppdev->Pointer; if (pgp->Enabled) { return; } pgp->Enabled = TRUE; /* Check if we have any mouse pointer */ if (!pgp->psurfSave) return; /* Calculate pointer coordinates */ pt.x = ppdev->ptlPointer.x - pgp->HotSpot.x; pt.y = ppdev->ptlPointer.y - pgp->HotSpot.y; /* Calculate the rect on the surface */ rclSurf.left = max(pt.x, 0); rclSurf.top = max(pt.y, 0); rclSurf.right = min(pt.x + pgp->Size.cx, psoDest->sizlBitmap.cx); rclSurf.bottom = min(pt.y + pgp->Size.cy, psoDest->sizlBitmap.cy); /* Calculate the rect in the pointer bitmap */ rclPointer.left = rclSurf.left - pt.x; rclPointer.top = rclSurf.top - pt.y; rclPointer.right = min(pgp->Size.cx, psoDest->sizlBitmap.cx - pt.x); rclPointer.bottom = min(pgp->Size.cy, psoDest->sizlBitmap.cy - pt.y); /* Copy the pixels under the cursor to temporary surface. */ IntEngBitBlt(&pgp->psurfSave->SurfObj, psoDest, NULL, NULL, NULL, &rclPointer, (POINTL*)&rclSurf, NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); /* Blt the pointer on the screen. */ if (pgp->psurfColor) { if(!(pgp->flags & SPS_ALPHA)) { IntEngBitBlt(psoDest, &pgp->psurfMask->SurfObj, NULL, NULL, NULL, &rclSurf, (POINTL*)&rclPointer, NULL, NULL, NULL, ROP4_SRCAND); IntEngBitBlt(psoDest, &pgp->psurfColor->SurfObj, NULL, NULL, NULL, &rclSurf, (POINTL*)&rclPointer, NULL, NULL, NULL, ROP4_SRCINVERT); } else { BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } }; EXLATEOBJ exlo; EXLATEOBJ_vInitialize(&exlo, &gpalRGB, ppdev->ppalSurf, 0, 0, 0); IntEngAlphaBlend(psoDest, &pgp->psurfColor->SurfObj, NULL, &exlo.xlo, &rclSurf, &rclPointer, &blendobj); EXLATEOBJ_vCleanup(&exlo); } } else { IntEngBitBlt(psoDest, &pgp->psurfMask->SurfObj, NULL, NULL, NULL, &rclSurf, (POINTL*)&rclPointer, NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCAND)); rclPointer.top += pgp->Size.cy; IntEngBitBlt(psoDest, &pgp->psurfMask->SurfObj, NULL, NULL, NULL, &rclSurf, (POINTL*)&rclPointer, NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCINVERT)); } }
BOOL NTAPI GreGradientFill( HDC hdc, PTRIVERTEX pVertex, ULONG nVertex, PVOID pMesh, ULONG nMesh, ULONG ulMode) { PDC pdc; SURFACE *psurf; EXLATEOBJ exlo; RECTL rclExtent; POINTL ptlDitherOrg; ULONG i; BOOL bRet; /* Check parameters */ if (ulMode & GRADIENT_FILL_TRIANGLE) { PGRADIENT_TRIANGLE pTriangle = (PGRADIENT_TRIANGLE)pMesh; for (i = 0; i < nMesh; i++, pTriangle++) { if (pTriangle->Vertex1 >= nVertex || pTriangle->Vertex2 >= nVertex || pTriangle->Vertex3 >= nVertex) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } } } else { PGRADIENT_RECT pRect = (PGRADIENT_RECT)pMesh; for (i = 0; i < nMesh; i++, pRect++) { if (pRect->UpperLeft >= nVertex || pRect->LowerRight >= nVertex) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } } } /* Lock the output DC */ 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; } psurf = pdc->dclevel.pSurface; if(!psurf) { /* Memory DC with no surface selected */ DC_UnlockDc(pdc); return TRUE; // CHECKME } /* Calculate extent */ rclExtent.left = rclExtent.right = pVertex->x; rclExtent.top = rclExtent.bottom = pVertex->y; for (i = 0; i < nVertex; i++) { rclExtent.left = min(rclExtent.left, (pVertex + i)->x); rclExtent.right = max(rclExtent.right, (pVertex + i)->x); rclExtent.top = min(rclExtent.top, (pVertex + i)->y); rclExtent.bottom = max(rclExtent.bottom, (pVertex + i)->y); } IntLPtoDP(pdc, (LPPOINT)&rclExtent, 2); rclExtent.left += pdc->ptlDCOrig.x; rclExtent.right += pdc->ptlDCOrig.x; rclExtent.top += pdc->ptlDCOrig.y; rclExtent.bottom += pdc->ptlDCOrig.y; ptlDitherOrg.x = ptlDitherOrg.y = 0; IntLPtoDP(pdc, (LPPOINT)&ptlDitherOrg, 1); ptlDitherOrg.x += pdc->ptlDCOrig.x; ptlDitherOrg.y += pdc->ptlDCOrig.y; EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0, 0); ASSERT(pdc->rosdc.CombinedClip); DC_vPrepareDCsForBlit(pdc, rclExtent, NULL, rclExtent); bRet = IntEngGradientFill(&psurf->SurfObj, pdc->rosdc.CombinedClip, &exlo.xlo, pVertex, nVertex, pMesh, nMesh, &rclExtent, &ptlDitherOrg, ulMode); EXLATEOBJ_vCleanup(&exlo); DC_vFinishBlit(pdc, NULL); DC_UnlockDc(pdc); return bRet; }
BOOL APIENTRY NtGdiExtFloodFill( HDC hDC, INT XStart, INT YStart, COLORREF Color, UINT FillType) { PDC dc; PDC_ATTR pdcattr; SURFACE *psurf = NULL; EXLATEOBJ exlo; BOOL Ret = FALSE; RECTL DestRect; POINTL Pt; ULONG ConvColor; dc = DC_LockDc(hDC); if (!dc) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } if (dc->dctype == DC_TYPE_INFO) { DC_UnlockDc(dc); /* Yes, Windows really returns TRUE in this case */ return TRUE; } pdcattr = dc->pdcattr; if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(dc); if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY)) DC_vUpdateLineBrush(dc); Pt.x = XStart; Pt.y = YStart; IntLPtoDP(dc, (LPPOINT)&Pt, 1); Ret = NtGdiPtInRegion(dc->rosdc.hGCClipRgn, Pt.x, Pt.y); if (Ret) IntGdiGetRgnBox(dc->rosdc.hGCClipRgn,(LPRECT)&DestRect); else goto cleanup; DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect); psurf = dc->dclevel.pSurface; if (!psurf) { Ret = FALSE; goto cleanup; } EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0xffffff, 0); /* Only solid fills supported for now * How to support pattern brushes and non standard surfaces (not offering dib functions): * Version a (most likely slow): call DrvPatBlt for every pixel * Version b: create a flood mask and let MaskBlt blit a masked brush */ ConvColor = XLATEOBJ_iXlate(&exlo.xlo, Color); Ret = DIB_XXBPP_FloodFillSolid(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, ConvColor, FillType); EXLATEOBJ_vCleanup(&exlo); cleanup: DC_vFinishBlit(dc, NULL); DC_UnlockDc(dc); return Ret; }
BOOL APIENTRY NtGdiTransparentBlt( HDC hdcDst, INT xDst, INT yDst, INT cxDst, INT cyDst, HDC hdcSrc, INT xSrc, INT ySrc, INT cxSrc, INT cySrc, COLORREF TransColor) { PDC DCDest, DCSrc; HDC ahDC[2]; PGDIOBJ apObj[2]; RECTL rcDest, rcSrc; SURFACE *BitmapDest, *BitmapSrc = NULL; ULONG TransparentColor = 0; BOOL Ret = FALSE; EXLATEOBJ exlo; if ((hdcDst == NULL) || (hdcSrc == NULL)) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } TRACE("Locking DCs\n"); ahDC[0] = hdcDst; ahDC[1] = hdcSrc ; if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE)) { WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc); EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } DCDest = apObj[0]; DCSrc = apObj[1]; if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO) { GDIOBJ_vUnlockObject(&DCSrc->BaseObject); GDIOBJ_vUnlockObject(&DCDest->BaseObject); /* Yes, Windows really returns TRUE in this case */ return TRUE; } rcDest.left = xDst; rcDest.top = yDst; rcDest.right = rcDest.left + cxDst; rcDest.bottom = rcDest.top + cyDst; IntLPtoDP(DCDest, (LPPOINT)&rcDest, 2); rcDest.left += DCDest->ptlDCOrig.x; rcDest.top += DCDest->ptlDCOrig.y; rcDest.right += DCDest->ptlDCOrig.x; rcDest.bottom += DCDest->ptlDCOrig.y; rcSrc.left = xSrc; rcSrc.top = ySrc; rcSrc.right = rcSrc.left + cxSrc; rcSrc.bottom = rcSrc.top + cySrc; IntLPtoDP(DCSrc, (LPPOINT)&rcSrc, 2); rcSrc.left += DCSrc->ptlDCOrig.x; rcSrc.top += DCSrc->ptlDCOrig.y; rcSrc.right += DCSrc->ptlDCOrig.x; rcSrc.bottom += DCSrc->ptlDCOrig.y; /* Prepare for blit */ DC_vPrepareDCsForBlit(DCDest, &rcDest, DCSrc, &rcSrc); BitmapDest = DCDest->dclevel.pSurface; if (!BitmapDest) { goto done; } BitmapSrc = DCSrc->dclevel.pSurface; if (!BitmapSrc) { goto done; } /* Translate Transparent (RGB) Color to the source palette */ EXLATEOBJ_vInitialize(&exlo, &gpalRGB, BitmapSrc->ppal, 0, 0, 0); TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor); EXLATEOBJ_vCleanup(&exlo); EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj, &DCDest->co.ClipObj, &exlo.xlo, &rcDest, &rcSrc, TransparentColor, 0); EXLATEOBJ_vCleanup(&exlo); done: DC_vFinishBlit(DCDest, DCSrc); GDIOBJ_vUnlockObject(&DCDest->BaseObject); GDIOBJ_vUnlockObject(&DCSrc->BaseObject); return Ret; }
BOOL APIENTRY NtGdiExtFloodFill( HDC hDC, INT XStart, INT YStart, COLORREF Color, UINT FillType) { PDC dc; #if 0 PDC_ATTR pdcattr; #endif SURFACE *psurf; EXLATEOBJ exlo; BOOL Ret = FALSE; RECTL DestRect; POINTL Pt; ULONG ConvColor; dc = DC_LockDc(hDC); if (!dc) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } if (dc->dctype == DC_TYPE_INFO) { DC_UnlockDc(dc); /* Yes, Windows really returns TRUE in this case */ return TRUE; } if (!dc->dclevel.pSurface) { Ret = FALSE; goto cleanup; } #if 0 pdcattr = dc->pdcattr; #endif Pt.x = XStart; Pt.y = YStart; IntLPtoDP(dc, (LPPOINT)&Pt, 1); DC_vPrepareDCsForBlit(dc, &DestRect, NULL, NULL); /// FIXME: what about prgnVIS? And what about REAL clipping? psurf = dc->dclevel.pSurface; if (dc->prgnRao) { Ret = REGION_PtInRegion(dc->prgnRao, Pt.x, Pt.y); if (Ret) REGION_GetRgnBox(dc->prgnRao, (LPRECT)&DestRect); else { DC_vFinishBlit(dc, NULL); goto cleanup; } } else { RECTL_vSetRect(&DestRect, 0, 0, psurf->SurfObj.sizlBitmap.cx, psurf->SurfObj.sizlBitmap.cy); } EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0xffffff, 0); /* Only solid fills supported for now * How to support pattern brushes and non standard surfaces (not offering dib functions): * Version a (most likely slow): call DrvPatBlt for every pixel * Version b: create a flood mask and let MaskBlt blit a masked brush */ ConvColor = XLATEOBJ_iXlate(&exlo.xlo, Color); Ret = DIB_XXBPP_FloodFillSolid(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, ConvColor, FillType); DC_vFinishBlit(dc, NULL); EXLATEOBJ_vCleanup(&exlo); cleanup: DC_UnlockDc(dc); return Ret; }
BOOL NTAPI EBRUSHOBJ_bRealizeBrush(EBRUSHOBJ *pebo, BOOL bCallDriver) { BOOL bResult; PFN_DrvRealizeBrush pfnRealizeBrush = NULL; PSURFACE psurfPattern; SURFOBJ *psoMask; PPDEVOBJ ppdev; EXLATEOBJ exlo; PPALETTE ppalPattern; PBRUSH pbr = pebo->pbrush; HBITMAP hbmPattern; ULONG iHatch; /* All EBRUSHOBJs have a surface, see EBRUSHOBJ_vInit */ ASSERT(pebo->psurfTrg); ppdev = (PPDEVOBJ)pebo->psurfTrg->SurfObj.hdev; if (!ppdev) ppdev = gppdevPrimary; if (bCallDriver) { /* Get the Drv function */ pfnRealizeBrush = ppdev->DriverFunctions.RealizeBrush; if (pfnRealizeBrush == NULL) { ERR("No DrvRealizeBrush. Cannot realize brush\n"); return FALSE; } /* Get the mask */ psoMask = EBRUSHOBJ_psoMask(pebo); } else { /* Use the Eng function */ pfnRealizeBrush = EngRealizeBrush; /* We don't handle the mask bitmap here. We do this only on demand */ psoMask = NULL; } /* Check if this is a hatch brush */ if (pbr->flAttrs & BR_IS_HATCH) { /* Get the hatch brush pattern from the PDEV */ hbmPattern = (HBITMAP)ppdev->ahsurf[pbr->iHatch]; iHatch = pbr->iHatch; } else { /* Use the brushes pattern */ hbmPattern = pbr->hbmPattern; iHatch = -1; } psurfPattern = SURFACE_ShareLockSurface(hbmPattern); ASSERT(psurfPattern); ASSERT(psurfPattern->ppal); /* DIB brushes with DIB_PAL_COLORS usage need a new palette */ if (pbr->flAttrs & BR_IS_DIBPALCOLORS) { /* Create a palette with the colors from the DC */ ppalPattern = FixupDIBBrushPalette(psurfPattern->ppal, pebo->ppalDC); if (ppalPattern == NULL) { ERR("FixupDIBBrushPalette() failed.\n"); return FALSE; } pebo->ppalDIB = ppalPattern; } else { /* The palette is already as it should be */ ppalPattern = psurfPattern->ppal; } /* Initialize XLATEOBJ for the brush */ EXLATEOBJ_vInitialize(&exlo, ppalPattern, pebo->psurfTrg->ppal, 0, pebo->crCurrentBack, pebo->crCurrentText); /* Create the realization */ bResult = pfnRealizeBrush(&pebo->BrushObject, &pebo->psurfTrg->SurfObj, &psurfPattern->SurfObj, psoMask, &exlo.xlo, iHatch); /* Cleanup the XLATEOBJ */ EXLATEOBJ_vCleanup(&exlo); /* Unlock surface */ SURFACE_ShareUnlockSurface(psurfPattern); return bResult; }
/* 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; }