NTAPI EBRUSHOBJ_psoMask(EBRUSHOBJ *pebo) { HBITMAP hbmMask; PSURFACE psurfMask; PPDEVOBJ ppdev; /* Check if we don't have a mask yet */ if (pebo->psoMask == NULL) { /* Check if this is a hatch brush */ if (pebo->flattrs & BR_IS_HATCH) { /* Get the PDEV */ ppdev = (PPDEVOBJ)pebo->psurfTrg->SurfObj.hdev; if (!ppdev) ppdev = gppdevPrimary; /* Use the hatch bitmap as the mask */ hbmMask = (HBITMAP)ppdev->ahsurf[pebo->pbrush->iHatch]; psurfMask = SURFACE_ShareLockSurface(hbmMask); if (psurfMask == NULL) { ERR("Failed to lock hatch brush for PDEV %p, iHatch %lu\n", ppdev, pebo->pbrush->iHatch); return NULL; } NT_ASSERT(psurfMask->SurfObj.iBitmapFormat == BMF_1BPP); pebo->psoMask = &psurfMask->SurfObj; } } return pebo->psoMask; }
PSURFACE NTAPI PDEVOBJ_pSurface( PPDEVOBJ ppdev) { HSURF hsurf; /* Check if we already have a surface */ if (ppdev->pSurface) { /* Increment reference count */ GDIOBJ_vReferenceObjectByPointer(&ppdev->pSurface->BaseObject); } else { /* Call the drivers DrvEnableSurface */ hsurf = ppdev->pldev->pfn.EnableSurface(ppdev->dhpdev); /* Lock the surface */ ppdev->pSurface = SURFACE_ShareLockSurface(hsurf); } DPRINT("PDEVOBJ_pSurface() returning %p\n", ppdev->pSurface); return ppdev->pSurface; }
APIENTRY EngLockSurface( _In_ HSURF hsurf) { SURFACE *psurf = SURFACE_ShareLockSurface(hsurf); return psurf ? &psurf->SurfObj : NULL; }
/** * This function is not exported, because it makes no sense for * The driver to punt back to this function */ BOOL APIENTRY EngRealizeBrush( BRUSHOBJ *pbo, SURFOBJ *psoDst, SURFOBJ *psoPattern, SURFOBJ *psoMask, XLATEOBJ *pxlo, ULONG iHatch) { EBRUSHOBJ *pebo; HBITMAP hbmpRealize; SURFOBJ *psoRealize; PSURFACE psurfRealize; POINTL ptlSrc = {0, 0}; RECTL rclDest; ULONG lWidth; /* Calculate width in bytes of the realized brush */ lWidth = WIDTH_BYTES_ALIGN32(psoPattern->sizlBitmap.cx, BitsPerFormat(psoDst->iBitmapFormat)); /* Allocate a bitmap */ hbmpRealize = EngCreateBitmap(psoPattern->sizlBitmap, lWidth, psoDst->iBitmapFormat, BMF_NOZEROINIT, NULL); if (!hbmpRealize) { return FALSE; } /* Lock the bitmap */ psurfRealize = SURFACE_ShareLockSurface(hbmpRealize); /* Already delete the pattern bitmap (will be kept until dereferenced) */ EngDeleteSurface((HSURF)hbmpRealize); if (!psurfRealize) { return FALSE; } /* Copy the bits to the new format bitmap */ rclDest.left = rclDest.top = 0; rclDest.right = psoPattern->sizlBitmap.cx; rclDest.bottom = psoPattern->sizlBitmap.cy; psoRealize = &psurfRealize->SurfObj; EngCopyBits(psoRealize, psoPattern, NULL, pxlo, &rclDest, &ptlSrc); pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject); pebo->pengbrush = (PVOID)psurfRealize; return TRUE; }
INIT_FUNCTION NTSTATUS NTAPI InitDcImpl() { psurfDefaultBitmap = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]); if (!psurfDefaultBitmap) return STATUS_UNSUCCESSFUL; pbrDefaultBrush = BRUSH_ShareLockBrush(StockObjects[BLACK_BRUSH]); if (!pbrDefaultBrush) return STATUS_UNSUCCESSFUL; return STATUS_SUCCESS; }
BOOL APIENTRY EngDeleteSurface( _In_ _Post_ptr_invalid_ HSURF hsurf) { PSURFACE psurf; psurf = SURFACE_ShareLockSurface(hsurf); if (!psurf) { DPRINT1("Could not reference surface %p to delete\n", hsurf); return FALSE; } GDIOBJ_vDeleteObject(&psurf->BaseObject); return TRUE; }
BOOL APIENTRY EngAssociateSurface( _In_ HSURF hsurf, _In_ HDEV hdev, _In_ FLONG flHooks) { SURFOBJ *pso; PSURFACE psurf; PDEVOBJ* ppdev; PPALETTE ppal; ppdev = (PDEVOBJ*)hdev; /* Lock the surface */ psurf = SURFACE_ShareLockSurface(hsurf); if (!psurf) { return FALSE; } pso = &psurf->SurfObj; /* Associate the hdev */ pso->hdev = hdev; pso->dhpdev = ppdev->dhpdev; /* Hook up specified functions */ psurf->flags &= ~HOOK_FLAGS; psurf->flags |= (flHooks & HOOK_FLAGS); /* Assign the PDEV's palette */ ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault); SURFACE_vSetPalette(psurf, ppal); PALETTE_ShareUnlockPalette(ppal); SURFACE_ShareUnlockSurface(psurf); return TRUE; }
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; }
BOOL APIENTRY NtGdiMaskBlt( HDC hdcDest, INT nXDest, INT nYDest, INT nWidth, INT nHeight, HDC hdcSrc, INT nXSrc, INT nYSrc, HBITMAP hbmMask, INT xMask, INT yMask, DWORD dwRop, IN DWORD crBackColor) { PDC DCDest; PDC DCSrc = NULL; HDC ahDC[2]; PGDIOBJ apObj[2]; PDC_ATTR pdcattr = NULL; SURFACE *BitmapDest, *BitmapSrc = NULL, *psurfMask = NULL; RECTL DestRect, SourceRect; POINTL SourcePoint, MaskPoint; BOOL Status = FALSE; EXLATEOBJ exlo; XLATEOBJ *XlateObj = NULL; BOOL UsesSource; FIXUP_ROP(dwRop); // FIXME: why do we need this??? //DPRINT1("dwRop : 0x%08x\n", dwRop); UsesSource = ROP_USES_SOURCE(dwRop); if (!hdcDest || (UsesSource && !hdcSrc)) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } /* Check if we need a mask and have a mask bitmap */ if (ROP_USES_MASK(dwRop) && (hbmMask != NULL)) { /* Reference the mask bitmap */ psurfMask = SURFACE_ShareLockSurface(hbmMask); if (psurfMask == NULL) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } /* Make sure the mask bitmap is 1 BPP */ if (gajBitsPerFormat[psurfMask->SurfObj.iBitmapFormat] != 1) { EngSetLastError(ERROR_INVALID_PARAMETER); SURFACE_ShareUnlockSurface(psurfMask); return FALSE; } } else { /* We use NULL, if we need a mask, the Eng function will take care of that and use the brushobject to get a mask */ psurfMask = NULL; } MaskPoint.x = xMask; MaskPoint.y = yMask; /* Take care of source and destination bitmap */ TRACE("Locking DCs\n"); ahDC[0] = hdcDest; ahDC[1] = UsesSource ? hdcSrc : NULL; if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE)) { WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDest, hdcSrc); EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } DCDest = apObj[0]; DCSrc = apObj[1]; ASSERT(DCDest); if (NULL == DCDest) { if(DCSrc) DC_UnlockDc(DCSrc); WARN("Invalid destination dc handle (0x%p) passed to NtGdiBitBlt\n", hdcDest); return FALSE; } if (DCDest->dctype == DC_TYPE_INFO) { if(DCSrc) DC_UnlockDc(DCSrc); DC_UnlockDc(DCDest); /* Yes, Windows really returns TRUE in this case */ return TRUE; } if (UsesSource) { ASSERT(DCSrc); if (DCSrc->dctype == DC_TYPE_INFO) { DC_UnlockDc(DCDest); DC_UnlockDc(DCSrc); /* Yes, Windows really returns TRUE in this case */ return TRUE; } } pdcattr = DCDest->pdcattr; DestRect.left = nXDest; DestRect.top = nYDest; DestRect.right = nXDest + nWidth; DestRect.bottom = nYDest + nHeight; IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2); DestRect.left += DCDest->ptlDCOrig.x; DestRect.top += DCDest->ptlDCOrig.y; DestRect.right += DCDest->ptlDCOrig.x; DestRect.bottom += DCDest->ptlDCOrig.y; SourcePoint.x = nXSrc; SourcePoint.y = nYSrc; if (UsesSource) { IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1); SourcePoint.x += DCSrc->ptlDCOrig.x; SourcePoint.y += DCSrc->ptlDCOrig.y; /* Calculate Source Rect */ SourceRect.left = SourcePoint.x; SourceRect.top = SourcePoint.y; SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left; SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ; } else { SourceRect.left = 0; SourceRect.top = 0; SourceRect.right = 0; SourceRect.bottom = 0; } /* Prepare blit */ DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect); if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(DCDest); /* Determine surfaces to be used in the bitblt */ BitmapDest = DCDest->dclevel.pSurface; if (!BitmapDest) goto cleanup; if (UsesSource) { { BitmapSrc = DCSrc->dclevel.pSurface; if (!BitmapSrc) goto cleanup; } } /* Create the XLATEOBJ. */ if (UsesSource) { EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); XlateObj = &exlo.xlo; } /* Perform the bitblt operation */ Status = IntEngBitBlt(&BitmapDest->SurfObj, BitmapSrc ? &BitmapSrc->SurfObj : NULL, psurfMask ? &psurfMask->SurfObj : NULL, &DCDest->co.ClipObj, XlateObj, &DestRect, &SourcePoint, &MaskPoint, &DCDest->eboFill.BrushObject, &DCDest->dclevel.pbrFill->ptOrigin, ROP_TO_ROP4(dwRop)); if (UsesSource) EXLATEOBJ_vCleanup(&exlo); cleanup: DC_vFinishBlit(DCDest, DCSrc); if (UsesSource) { DC_UnlockDc(DCSrc); } DC_UnlockDc(DCDest); if(psurfMask) SURFACE_ShareUnlockSurface(psurfMask); return Status; }
/* * @implemented */ HBITMAP APIENTRY NtGdiSelectBitmap( IN HDC hdc, IN HBITMAP hbmp) { PDC pdc; PDC_ATTR pdcattr; HBITMAP hbmpOld; PSURFACE psurfNew; HRGN hVisRgn; SIZEL sizlBitmap = {1, 1}; HDC hdcOld; ASSERT_NOGDILOCKS(); /* Verify parameters */ if (hdc == NULL || hbmp == NULL) return NULL; /* First lock the DC */ pdc = DC_LockDc(hdc); if (!pdc) { return NULL; } pdcattr = pdc->pdcattr; /* Must be a memory dc to select a bitmap */ if (pdc->dctype != DC_TYPE_MEMORY) { DC_UnlockDc(pdc); return NULL; } /* Check if there was a bitmap selected before */ if (pdc->dclevel.pSurface) { /* Return its handle */ hbmpOld = pdc->dclevel.pSurface->BaseObject.hHmgr; } else { /* Return default bitmap */ hbmpOld = StockObjects[DEFAULT_BITMAP]; } /* Check if the default bitmap was passed */ if (hbmp == StockObjects[DEFAULT_BITMAP]) { psurfNew = NULL; // HACK psurfNew = SURFACE_ShareLockSurface(hbmp); } else { /* Reference the new bitmap and check if it's valid */ psurfNew = SURFACE_ShareLockSurface(hbmp); if (!psurfNew) { DC_UnlockDc(pdc); return NULL; } /* Set the bitmp's hdc */ hdcOld = InterlockedCompareExchangePointer((PVOID*)&psurfNew->hdc, hdc, 0); if (hdcOld != NULL && hdcOld != hdc) { /* The bitmap is already selected, fail */ SURFACE_ShareUnlockSurface(psurfNew); DC_UnlockDc(pdc); return NULL; } /* Get the bitmap size */ sizlBitmap = psurfNew->SurfObj.sizlBitmap; /* Check if the bitmap is a dibsection */ if(psurfNew->hSecure) { /* Set DIBSECTION attribute */ pdcattr->ulDirty_ |= DC_DIBSECTION; } else { pdcattr->ulDirty_ &= ~DC_DIBSECTION; } } /* Select the new surface, release the old */ DC_vSelectSurface(pdc, psurfNew); /* Set the new size */ pdc->dclevel.sizl = sizlBitmap; /* Release one reference we added */ SURFACE_ShareUnlockSurface(psurfNew); /* Mark the dc brushes invalid */ pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE; /* Unlock the DC */ DC_UnlockDc(pdc); /* FIXME; improve by using a region without a handle and selecting it */ hVisRgn = IntSysCreateRectRgn( 0, 0, sizlBitmap.cx, sizlBitmap.cy); if (hVisRgn) { GdiSelectVisRgn(hdc, hVisRgn); GreDeleteObject(hVisRgn); } /* Return the old bitmap handle */ return hbmpOld; }
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; }
BOOL APIENTRY EngModifySurface( _In_ HSURF hsurf, _In_ HDEV hdev, _In_ FLONG flHooks, _In_ FLONG flSurface, _In_ DHSURF dhsurf, _In_ PVOID pvScan0, _In_ LONG lDelta, _Reserved_ PVOID pvReserved) { SURFOBJ *pso; PSURFACE psurf; PDEVOBJ* ppdev; PPALETTE ppal; /* Lock the surface */ psurf = SURFACE_ShareLockSurface(hsurf); if (psurf == NULL) { DPRINT1("Failed to reference surface %p\n", hsurf); return FALSE; } ppdev = (PDEVOBJ*)hdev; pso = &psurf->SurfObj; pso->dhsurf = dhsurf; /* Associate the hdev */ pso->hdev = hdev; pso->dhpdev = ppdev->dhpdev; /* Hook up specified functions */ psurf->flags &= ~HOOK_FLAGS; psurf->flags |= (flHooks & HOOK_FLAGS); /* Assign the PDEV's palette */ ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault); SURFACE_vSetPalette(psurf, ppal); PALETTE_ShareUnlockPalette(ppal); /* Update surface flags */ if (flSurface & MS_NOTSYSTEMMEMORY) pso->fjBitmap |= BMF_NOTSYSMEM; else pso->fjBitmap &= ~BMF_NOTSYSMEM; if (flSurface & MS_SHAREDACCESS) psurf->flags |= SHAREACCESS_SURFACE; else psurf->flags &= ~SHAREACCESS_SURFACE; /* Check if the caller passed bitmap bits */ if ((pvScan0 != NULL) && (lDelta != 0)) { /* Update the fields */ pso->pvScan0 = pvScan0; pso->lDelta = lDelta; /* This is a bitmap now! */ pso->iType = STYPE_BITMAP; /* Check memory layout */ if (lDelta > 0) { /* Topdown is the normal way */ pso->cjBits = lDelta * pso->sizlBitmap.cy; pso->pvBits = pso->pvScan0; pso->fjBitmap |= BMF_TOPDOWN; } else { /* Inversed bitmap (bottom up) */ pso->cjBits = (-lDelta) * pso->sizlBitmap.cy; pso->pvBits = (PCHAR)pso->pvScan0 - pso->cjBits - lDelta; pso->fjBitmap &= ~BMF_TOPDOWN; } } else { /* Set bits to NULL */ pso->pvBits = NULL; pso->pvScan0 = NULL; pso->lDelta = 0; /* Set appropriate surface type */ if (pso->iType != STYPE_DEVICE) pso->iType = STYPE_DEVBITMAP; } SURFACE_ShareUnlockSurface(psurf); return TRUE; }
VOID NTAPI DC_vInitDc( PDC pdc, DCTYPE dctype, PPDEVOBJ ppdev) { /* Setup some basic fields */ pdc->dctype = dctype; pdc->ppdev = ppdev; pdc->dhpdev = ppdev->dhpdev; pdc->hsem = ppdev->hsemDevLock; pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps; pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2; pdc->fs = DC_DIRTY_RAO; /* Setup dc attribute */ pdc->pdcattr = &pdc->dcattr; pdc->dcattr.pvLDC = NULL; pdc->dcattr.ulDirty_ = DIRTY_DEFAULT; if (ppdev == gppdevPrimary) pdc->dcattr.ulDirty_ |= DC_PRIMARY_DISPLAY; /* Setup the DC size */ if (dctype == DCTYPE_MEMORY) { /* Memory DCs have a 1 x 1 bitmap by default */ pdc->dclevel.sizl.cx = 1; pdc->dclevel.sizl.cy = 1; } else { /* Other DC's are as big as the related PDEV */ pdc->dclevel.sizl.cx = ppdev->gdiinfo.ulHorzRes; pdc->dclevel.sizl.cy = ppdev->gdiinfo.ulVertRes; } /* Setup Window rect based on DC size */ pdc->erclWindow.left = 0; pdc->erclWindow.top = 0; pdc->erclWindow.right = pdc->dclevel.sizl.cx; pdc->erclWindow.bottom = pdc->dclevel.sizl.cy; if (dctype == DCTYPE_DIRECT) { /* Direct DCs get the surface from the PDEV */ pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev); pdc->erclBounds.left = 0x7fffffff; pdc->erclBounds.top = 0x7fffffff; pdc->erclBounds.right = 0x80000000; pdc->erclBounds.bottom = 0x80000000; pdc->erclBoundsApp.left = 0xffffffff; pdc->erclBoundsApp.top = 0xfffffffc; pdc->erclBoundsApp.right = 0x00007ffc; // FIXME pdc->erclBoundsApp.bottom = 0x00000333; // FIXME pdc->erclClip = pdc->erclBounds; // pdc->co pdc->fs |= DC_SYNCHRONIZEACCESS | DC_ACCUM_APP | DC_PERMANANT | DC_DISPLAY; } else { /* Non-direct DCs don't have a surface by default */ pdc->dclevel.pSurface = NULL; // FIXME: HACK, because our code expects a surface pdc->dclevel.pSurface = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]); pdc->erclBounds.left = 0; pdc->erclBounds.top = 0; pdc->erclBounds.right = 0; pdc->erclBounds.bottom = 0; pdc->erclBoundsApp = pdc->erclBounds; pdc->erclClip = pdc->erclWindow; // pdc->co = NULL } // pdc->dcattr.VisRectRegion: /* Setup coordinate transformation data */ pdc->dclevel.mxWorldToDevice = gmxWorldToDeviceDefault; pdc->dclevel.mxDeviceToWorld = gmxDeviceToWorldDefault; pdc->dclevel.mxWorldToPage = gmxWorldToPageDefault; pdc->dclevel.efM11PtoD = gef16; pdc->dclevel.efM22PtoD = gef16; pdc->dclevel.efDxPtoD = gef0; pdc->dclevel.efDyPtoD = gef0; pdc->dclevel.efM11_TWIPS = gef0; pdc->dclevel.efM22_TWIPS = gef0; pdc->dclevel.efPr11 = gef0; pdc->dclevel.efPr22 = gef0; pdc->dcattr.mxWorldToDevice = pdc->dclevel.mxWorldToDevice; pdc->dcattr.mxDeviceToWorld = pdc->dclevel.mxDeviceToWorld; pdc->dcattr.mxWorldToPage = pdc->dclevel.mxWorldToPage; pdc->dcattr.efM11PtoD = pdc->dclevel.efM11PtoD; pdc->dcattr.efM22PtoD = pdc->dclevel.efM22PtoD; pdc->dcattr.efDxPtoD = pdc->dclevel.efDxPtoD; pdc->dcattr.efDyPtoD = pdc->dclevel.efDyPtoD; pdc->dcattr.iMapMode = MM_TEXT; pdc->dcattr.dwLayout = 0; pdc->dcattr.flXform = PAGE_TO_DEVICE_SCALE_IDENTITY | PAGE_TO_DEVICE_IDENTITY | WORLD_TO_PAGE_IDENTITY; /* Setup more coordinates */ pdc->ptlDCOrig.x = 0; pdc->ptlDCOrig.y = 0; pdc->dcattr.lWindowOrgx = 0; pdc->dcattr.ptlWindowOrg.x = 0; pdc->dcattr.ptlWindowOrg.y = 0; pdc->dcattr.szlWindowExt.cx = 1; pdc->dcattr.szlWindowExt.cy = 1; pdc->dcattr.ptlViewportOrg.x = 0; pdc->dcattr.ptlViewportOrg.y = 0; pdc->dcattr.szlViewportExt.cx = 1; pdc->dcattr.szlViewportExt.cy = 1; pdc->dcattr.szlVirtualDevicePixel.cx = ppdev->gdiinfo.ulHorzRes; pdc->dcattr.szlVirtualDevicePixel.cy = ppdev->gdiinfo.ulVertRes; pdc->dcattr.szlVirtualDeviceMm.cx = ppdev->gdiinfo.ulHorzSize; pdc->dcattr.szlVirtualDeviceMm.cy = ppdev->gdiinfo.ulVertSize; pdc->dcattr.szlVirtualDeviceSize.cx = 0; pdc->dcattr.szlVirtualDeviceSize.cy = 0; /* Setup regions */ pdc->prgnAPI = NULL; pdc->prgnRao = NULL; /* Allocate a Vis region */ pdc->prgnVis = IntSysCreateRectpRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy); ASSERT(pdc->prgnVis); /* Setup palette */ pdc->dclevel.hpal = StockObjects[DEFAULT_PALETTE]; pdc->dclevel.ppal = PALETTE_ShareLockPalette(pdc->dclevel.hpal); /* Setup path */ pdc->dclevel.hPath = NULL; pdc->dclevel.flPath = 0; // pdc->dclevel.lapath: /* Setup colors */ pdc->dcattr.crBackgroundClr = RGB(0xff, 0xff, 0xff); pdc->dcattr.ulBackgroundClr = RGB(0xff, 0xff, 0xff); pdc->dcattr.crForegroundClr = RGB(0, 0, 0); pdc->dcattr.ulForegroundClr = RGB(0, 0, 0); pdc->dcattr.crBrushClr = RGB(0xff, 0xff, 0xff); pdc->dcattr.ulBrushClr = RGB(0xff, 0xff, 0xff); pdc->dcattr.crPenClr = RGB(0, 0, 0); pdc->dcattr.ulPenClr = RGB(0, 0, 0); /* Select the default fill and line brush */ pdc->dcattr.hbrush = StockObjects[WHITE_BRUSH]; pdc->dcattr.hpen = StockObjects[BLACK_PEN]; pdc->dclevel.pbrFill = BRUSH_ShareLockBrush(pdc->pdcattr->hbrush); pdc->dclevel.pbrLine = PEN_ShareLockPen(pdc->pdcattr->hpen); pdc->dclevel.ptlBrushOrigin.x = 0; pdc->dclevel.ptlBrushOrigin.y = 0; pdc->dcattr.ptlBrushOrigin = pdc->dclevel.ptlBrushOrigin; /* Initialize EBRUSHOBJs */ EBRUSHOBJ_vInit(&pdc->eboFill, pdc->dclevel.pbrFill, pdc); EBRUSHOBJ_vInit(&pdc->eboLine, pdc->dclevel.pbrLine, pdc); EBRUSHOBJ_vInit(&pdc->eboText, pbrDefaultBrush, pdc); EBRUSHOBJ_vInit(&pdc->eboBackground, pbrDefaultBrush, pdc); /* Setup fill data */ pdc->dcattr.jROP2 = R2_COPYPEN; pdc->dcattr.jBkMode = 2; pdc->dcattr.lBkMode = 2; pdc->dcattr.jFillMode = ALTERNATE; pdc->dcattr.lFillMode = 1; pdc->dcattr.jStretchBltMode = 1; pdc->dcattr.lStretchBltMode = 1; pdc->ptlFillOrigin.x = 0; pdc->ptlFillOrigin.y = 0; /* Setup drawing position */ pdc->dcattr.ptlCurrent.x = 0; pdc->dcattr.ptlCurrent.y = 0; pdc->dcattr.ptfxCurrent.x = 0; pdc->dcattr.ptfxCurrent.y = 0; /* Setup ICM data */ pdc->dclevel.lIcmMode = 0; pdc->dcattr.lIcmMode = 0; pdc->dcattr.hcmXform = NULL; pdc->dcattr.flIcmFlags = 0; pdc->dcattr.IcmBrushColor = CLR_INVALID; pdc->dcattr.IcmPenColor = CLR_INVALID; pdc->dcattr.pvLIcm = NULL; pdc->dcattr.hColorSpace = NULL; // FIXME: 0189001f pdc->dclevel.pColorSpace = NULL; // FIXME pdc->pClrxFormLnk = NULL; // pdc->dclevel.ca = /* Setup font data */ pdc->hlfntCur = NULL; // FIXME: 2f0a0cf8 pdc->pPFFList = NULL; pdc->flSimulationFlags = 0; pdc->lEscapement = 0; pdc->prfnt = NULL; pdc->dcattr.flFontMapper = 0; pdc->dcattr.flTextAlign = 0; pdc->dcattr.lTextAlign = 0; pdc->dcattr.lTextExtra = 0; pdc->dcattr.lRelAbs = 1; pdc->dcattr.lBreakExtra = 0; pdc->dcattr.cBreak = 0; pdc->dcattr.hlfntNew = StockObjects[SYSTEM_FONT]; // pdc->dclevel.pFont = LFONT_ShareLockFont(pdc->dcattr.hlfntNew); /* Other stuff */ pdc->hdcNext = NULL; pdc->hdcPrev = NULL; pdc->ipfdDevMax = 0x0000ffff; pdc->ulCopyCount = -1; pdc->ptlDoBanding.x = 0; pdc->ptlDoBanding.y = 0; pdc->dclevel.lSaveDepth = 1; pdc->dclevel.hdcSave = NULL; pdc->dcattr.iGraphicsMode = GM_COMPATIBLE; pdc->dcattr.iCS_CP = 0; pdc->pSurfInfo = NULL; }
/* 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; }